/*******************************************************************************
* Copyright (c) 2007, 2016 Intel Corporation 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:
* Intel Corporation - Initial API and implementation
* Serge Beauchamp (Freescale Semiconductor) - Bug 406545
*******************************************************************************/
package org.eclipse.cdt.managedbuilder.ui.properties;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import org.eclipse.cdt.core.settings.model.ICResourceDescription;
import org.eclipse.cdt.managedbuilder.core.BuildListComparator;
import org.eclipse.cdt.managedbuilder.core.IBuildObject;
import org.eclipse.cdt.managedbuilder.core.IBuilder;
import org.eclipse.cdt.managedbuilder.core.IConfiguration;
import org.eclipse.cdt.managedbuilder.core.IFileInfo;
import org.eclipse.cdt.managedbuilder.core.IFolderInfo;
import org.eclipse.cdt.managedbuilder.core.IResourceInfo;
import org.eclipse.cdt.managedbuilder.core.ITool;
import org.eclipse.cdt.managedbuilder.core.IToolChain;
import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;
import org.eclipse.cdt.managedbuilder.internal.core.IRealBuildObjectAssociation;
import org.eclipse.cdt.managedbuilder.internal.core.ToolChain;
import org.eclipse.cdt.managedbuilder.internal.ui.Messages;
import org.eclipse.cdt.managedbuilder.tcmodification.CompatibilityStatus;
import org.eclipse.cdt.managedbuilder.tcmodification.IConfigurationModification;
import org.eclipse.cdt.managedbuilder.tcmodification.IConflict;
import org.eclipse.cdt.managedbuilder.tcmodification.IFileInfoModification;
import org.eclipse.cdt.managedbuilder.tcmodification.IFolderInfoModification;
import org.eclipse.cdt.managedbuilder.tcmodification.IModificationOperation;
import org.eclipse.cdt.managedbuilder.tcmodification.IToolChainModificationManager;
import org.eclipse.cdt.managedbuilder.tcmodification.IToolListModification;
import org.eclipse.cdt.managedbuilder.tcmodification.IToolModification;
import org.eclipse.cdt.ui.CDTSharedImages;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
/**
* @noextend This class is not intended to be subclassed by clients.
* @noinstantiate This class is not intended to be instantiated by clients.
*/
public class ToolChainEditTab extends AbstractCBuildPropertyTab {
private static final IToolChainModificationManager tcmmgr = ManagedBuildManager.getToolChainModificationManager();
private static final String NO_TC = Messages.StdProjectTypeHandler_0;
private static final IToolChain[] r_tcs = ManagedBuildManager.getRealToolChains();
private static final IBuilder[] r_bs = ManagedBuildManager.getRealBuilders();
private static final ITool[] r_tools = ManagedBuildManager.getRealTools();
private static final Color red = Display.getDefault().getSystemColor(SWT.COLOR_RED);
private static final String SPACE = " "; //$NON-NLS-1$
static private final Image IMG_WARNING = CDTSharedImages.getImage(CDTSharedImages.IMG_OBJS_REFACTORING_WARNING);
static private final Image IMG_ERROR = CDTSharedImages.getImage(CDTSharedImages.IMG_OBJS_REFACTORING_ERROR);
static private final Image IMG_INFO = CDTSharedImages.getImage(CDTSharedImages.IMG_OBJS_REFACTORING_INFO);
private Text text;
private Button b_dispCompatible;
private Combo c_toolchain;
private Combo c_builder;
private Combo c_tool;
private Button button_edit;
private Group tools_group;
private Group single_tool_group;
private Text st_builder;
private Text st_toolchain;
private Label st_tool;
private IBuilder[] v_bs;
private IToolChain[] v_tcs;
private ITool[] v_tools;
private IConfiguration cfg;
private IResourceInfo ri;
private IToolListModification mod;
@Override
public void createControls(Composite parent) {
super.createControls(parent);
usercomp.setLayout(new GridLayout(2, false));
b_dispCompatible = setupCheck(usercomp, Messages.ToolChainEditTab_0, 2, GridData.BEGINNING);
b_dispCompatible.setSelection(true);
setupLabel(usercomp, Messages.ToolChainEditTab_1, 1, GridData.BEGINNING);
c_toolchain = new Combo(usercomp, SWT.READ_ONLY | SWT.DROP_DOWN | SWT.BORDER);
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = 1;
c_toolchain.setLayoutData(gd);
c_toolchain.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
modifyToolchain();
}});
c_toolchain.setEnabled(!page.isForFile());
st_toolchain = new Text(usercomp, SWT.LEFT | SWT.READ_ONLY);
setupControl(st_toolchain, 2, GridData.FILL_HORIZONTAL);
st_toolchain.setForeground(red);
setupLabel(usercomp, Messages.ToolChainEditTab_2, 1, GridData.BEGINNING);
c_builder = new Combo(usercomp, SWT.READ_ONLY | SWT.DROP_DOWN | SWT.BORDER);
gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = 1;
c_builder.setLayoutData(gd);
c_builder.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
modifyBuilder();
}});
c_builder.setEnabled(page.isForProject());
st_builder = new Text(usercomp, SWT.LEFT | SWT.READ_ONLY);
setupControl(st_builder, 2, GridData.FILL_HORIZONTAL);
st_builder.setForeground(red);
// make table for tools list
if (page.isForFile()) {
single_tool_group = setupGroup(usercomp, Messages.ToolChainEditTab_5, 2, GridData.FILL_BOTH);
setupControl(single_tool_group, 2, GridData.FILL_BOTH);
c_tool = new Combo(single_tool_group, SWT.READ_ONLY | SWT.DROP_DOWN | SWT.BORDER);
gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = 2;
c_tool.setLayoutData(gd);
c_tool.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
saveToolSelected();
}});
st_tool = setupLabel(single_tool_group, EMPTY_STR, 2, GridData.FILL_HORIZONTAL);
st_tool.setForeground(red);
} else { // Folder or Project
tools_group = setupGroup(usercomp, Messages.ToolChainEditTab_3, 2, GridData.FILL_BOTH);
setupControl(tools_group, 2, GridData.FILL_BOTH);
text = new Text(tools_group, SWT.BORDER | SWT.WRAP | SWT.MULTI |
SWT.READ_ONLY | SWT.V_SCROLL | SWT.H_SCROLL);
gd = new GridData(GridData.FILL_BOTH);
gd.grabExcessHorizontalSpace = true;
text.setLayoutData(gd);
button_edit = new Button(tools_group, SWT.PUSH);
GridData gdb = new GridData(GridData.VERTICAL_ALIGN_CENTER);
gdb.grabExcessHorizontalSpace = false;
gdb.horizontalAlignment = SWT.FILL;
gdb.widthHint = 80;
button_edit.setLayoutData(gdb);
button_edit.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
modifyTools();
}});
button_edit.setLayoutData(new GridData(GridData.END));
button_edit.setText(Messages.ToolChainEditTab_4);
}
}
private IToolListModification getModification() {
if (ri instanceof IFolderInfo)
return tcmmgr.createModification((IFolderInfo)ri);
else
return tcmmgr.createModification((IFileInfo)ri);
}
@Override
protected void updateData(ICResourceDescription rcfg) {
if (page.isMultiCfg()) {
setAllVisible(false, null);
return;
} else {
setAllVisible(true, null);
}
cfg = getCfg(rcfg.getConfiguration());
ri = cfg.getResourceInfo(rcfg.getPath(), false);
mod = getModification();
updateData();
}
/**
* @since 8.2
*/
@Override
public boolean canSupportMultiCfg() {
return false;
}
private void updateData() {
showErrorMessage();
fillToolChainCombo();
fillBuilderCombo();
fillToolsList();
}
private void showErrorMessage() {
if (ri instanceof IFolderInfo) {
IFolderInfoModification foim = (IFolderInfoModification)mod;
IToolChain toolChain = ((IFolderInfoModification)mod).getToolChain();
IToolChain realToolChain = ManagedBuildManager.getRealToolChain(toolChain);
if (realToolChain==null) {
// The toolchain is not derived from extension
String errText = NLS.bind(Messages.ToolChainEditTab_OrphanedToolchain, toolChain.getId(), toolChain.getName());
st_toolchain.setText(errText);
} else if (foim.isToolChainCompatible()) {
st_toolchain.setText(EMPTY_STR);
} else {
String s = foim.getToolChainCompatibilityStatus().getMessage();
st_toolchain.setText(s);
}
st_builder.setText(EMPTY_STR);
if (foim instanceof IConfigurationModification) {
IConfigurationModification cm = (IConfigurationModification)foim;
if (!cm.isBuilderCompatible()) {
IBuilder builder = cfg.getBuilder();
IBuilder realBuilder = ManagedBuildManager.getRealBuilder(builder);
if (realBuilder==null) {
// The builder is not derived from extension
String errText = NLS.bind(Messages.ToolChainEditTab_OrphanedBuilder, builder.getId(), builder.getName());
st_builder.setText(errText);
} else {
CompatibilityStatus cs = cm.getBuilderCompatibilityStatus();
if (cs != null) {
String s = cs.getMessage();
st_builder.setText(s);
}
}
}
}
// } else { // FileInfo
// IFileInfoModification fim = (IFileInfoModification)mod;
// fim.getProjectToolModifications();
}
st_toolchain.setEnabled(!EMPTY_STR.equals(st_toolchain.getText()));
st_builder.setEnabled(!EMPTY_STR.equals(st_builder.getText()));
}
private void fillToolChainCombo() {
IToolChain realToolChain = null;
if (ri instanceof IFolderInfo) {
IToolChain toolChainInstance = ((IFolderInfoModification)mod).getToolChain();
realToolChain = ManagedBuildManager.getRealToolChain(toolChainInstance);
if (realToolChain==null)
realToolChain = toolChainInstance;
}
c_toolchain.removeAll();
boolean isMng = cfg.getBuilder().isManagedBuildOn();
ArrayList<IToolChain> list = new ArrayList<IToolChain>();
IToolChain[] tcs = r_tcs;
if (b_dispCompatible.getSelection() && (ri instanceof IFolderInfo)) {
IFolderInfoModification fim = (IFolderInfoModification)mod;
tcs = fim.getCompatibleToolChains();
IToolChain[] tcs1 = new IToolChain[tcs.length + 1];
System.arraycopy(tcs, 0, tcs1, 0, tcs.length);
tcs1[tcs.length] = realToolChain; // add existing toolchain
tcs = tcs1;
}
for (IToolChain tc : tcs) {
if ( tc.isSystemObject() && !(((ToolChain)tc).isPreferenceToolChain() && !isMng) ) {
// NO TOOLCHAIN
continue;
}
list.add(tc);
}
Collections.sort(list, BuildListComparator.getInstance());
int pos = -1;
v_tcs = list.toArray(new IToolChain[list.size()]);
for (int i=0; i<v_tcs.length; i++) {
c_toolchain.add(v_tcs[i].getUniqueRealName());
if (v_tcs[i].matches(realToolChain)) pos = i;
}
if (pos != -1) {
c_toolchain.select(pos);
c_builder.setEnabled(page.isForProject());
}
else {
c_toolchain.setText(EMPTY_STR); // unprobable case
c_builder.setEnabled(false);
}
}
private void fillBuilderCombo() {
IBuilder realBuilder = ManagedBuildManager.getRealBuilder(cfg.getBuilder());
if (realBuilder==null)
realBuilder = cfg.getBuilder();
int pos = -1;
c_builder.removeAll();
ArrayList<IBuilder> list = new ArrayList<IBuilder>();
IBuilder[] bs = r_bs;
if (b_dispCompatible.getSelection() && (ri instanceof IFolderInfo)) {
IFolderInfoModification fim = (IFolderInfoModification)mod;
if (fim instanceof IConfigurationModification) {
bs = ((IConfigurationModification)fim).getCompatibleBuilders();
IBuilder[] bs1 = new IBuilder[bs.length + 1];
System.arraycopy(bs, 0, bs1, 0, bs.length);
bs1[bs.length] = realBuilder;
bs = bs1;
}
}
for (int i=0; i<bs.length; i++) {
if (bs[i].isSystemObject() && ! bs[i].equals(realBuilder))
continue;
list.add(bs[i]);
}
bs = null;
Collections.sort(list, BuildListComparator.getInstance());
v_bs = list.toArray(new IBuilder[list.size()]);
for (int i=0; i<v_bs.length; i++) {
c_builder.add(v_bs[i].getUniqueRealName());
if (v_bs[i].matches(realBuilder)) pos = i;
}
if (pos != -1)
c_builder.select(pos);
else
c_builder.setText(EMPTY_STR);
}
private ITool getToolForFile() {
ITool[] tools = ((IFileInfoModification)mod).getProjectTools();
if (tools != null && tools.length > 0) {
for (int i=0; i<tools.length; i++) {
if (tools[i] != null && !tools[i].getCustomBuildStep()) {
return tools[i];
}
}
}
return null;
}
private void fillToolCombo(boolean add, ITool curr) {
c_tool.removeAll();
int pos = (curr == null) ? v_tools.length : -1;
for (int i=0; i<v_tools.length; i++) {
if (pos == -1 && curr.matches(v_tools[i])) {
pos = i;
c_tool.add(curr.getUniqueRealName());
} else {
c_tool.add(v_tools[i].getUniqueRealName());
}
}
// Add NO_TOOL
if (add) {
c_tool.add(Messages.ToolChainEditTab_6);
}
c_tool.select(pos);
}
private void fillToolsList() {
updateAllTools(); // modifies v_tools inside !!!
ToolChain tc = null;
if (ri instanceof IFolderInfo)
tc = (ToolChain)ManagedBuildManager.getRealToolChain(((IFolderInfo)ri).getToolChain());
if (page.isForFile()) { // Edit tool in combo for File
ITool curr = getToolForFile();
boolean canAddNO_TOOL = true;
if (ri instanceof IFileInfo && b_dispCompatible.getSelection())
canAddNO_TOOL = updateCompatibleTools(curr); // modifies v_tools inside !!!
fillToolCombo(canAddNO_TOOL, curr);
showToolStatus(curr);
} else if (tc != null && tc.isPreferenceToolChain()){ // display tools list for Folder and Project
tools_group.setVisible(false);
} else {
tools_group.setVisible(true);
String s = EMPTY_STR;
ITool[] tools = ri.getTools();
for (ITool tool : tools) {
s = s + tool.getUniqueRealName() + "\n"; //$NON-NLS-1$
}
text.setText(s);
}
}
private void updateAllTools() {
int cnt = 0;
v_tools = new ITool[r_tools.length];
for (ITool r_tool : r_tools) {
if (r_tool.isSystemObject()) continue;
if (r_tool.isAbstract()) continue;
v_tools[cnt++] = r_tool;
}
ITool[] tmp = new ITool[cnt];
System.arraycopy(v_tools, 0, tmp, 0, cnt);
Arrays.sort(tmp, BuildListComparator.getInstance());
v_tools = tmp;
}
private void showToolStatus(ITool tool) {
st_tool.setText(EMPTY_STR);
st_tool.setImage(null);
if (tool == null)
return;
IFileInfoModification fim = (IFileInfoModification)mod;
IToolModification tm = fim.getToolModification(tool);
if (tm != null && !tm.isCompatible()) {
CompatibilityStatus cs = tm.getCompatibilityStatus();
if (cs != null) {
st_tool.setText(cs.getMessage());
st_tool.setImage(getErrorIcon(cs));
}
}
}
private boolean updateCompatibleTools(ITool real) {
boolean result = false;
ArrayList<ITool> list = new ArrayList<ITool>();
IFileInfoModification fim = (IFileInfoModification)mod;
if (real != null) { // Current tool exists
real = ManagedBuildManager.getRealTool(real);
list.add(real);
IToolModification tm = fim.getToolModification(real);
IModificationOperation[] mos = tm.getSupportedOperations();
for (IModificationOperation mo : mos) {
ITool t = mo.getReplacementTool();
if (t == null)
result = true;
else {
if (! t.isSystemObject() && ! t.isAbstract())
list.add(t);
}
}
} else { // Current tool is NO_TOOL
result = true;
IToolModification[] tms = fim.getSystemToolModifications();
for (IToolModification tm : tms) {
IModificationOperation[] mos = tm.getSupportedOperations();
for (IModificationOperation mo : mos) {
if (mo.getReplacementTool() == null) {
ITool t = tm.getTool();
if (! t.isSystemObject() && ! t.isAbstract())
list.add(t);
break;
}
}
}
}
Collections.sort(list, BuildListComparator.getInstance());
v_tools = list.toArray(new ITool[list.size()]);
return result;
}
@Override
protected void checkPressed(SelectionEvent e) {
updateData();
}
@Override
protected void performApply(ICResourceDescription src,
ICResourceDescription dst) {
if (mod == null)
return;
IConfiguration cfg = getCfg(dst.getConfiguration());
try {
IToolListModification tlm = (ri instanceof IFolderInfo) ?
(IToolListModification)tcmmgr.createModification(cfg, (IFolderInfoModification)mod) :
(IToolListModification)tcmmgr.createModification(cfg, (IFileInfoModification)mod);
tlm.apply();
} catch (CoreException e) {
ManagedBuilderUIPlugin.log(e);
}
}
@Override
protected void performDefaults() {
if (mod != null) {
mod.restoreDefaults();
apply();
updateData();
}
}
@Override
protected void updateButtons() {} // Do nothing. No buttons to update.
private void saveToolSelected() {
IFileInfoModification fim = (IFileInfoModification)mod;
// Find old tool
ITool oldTool = null;
ITool[] ots = fim.getProjectTools();
for (int i=0; i<ots.length; i++) {
if (!ots[i].getCustomBuildStep()) {
oldTool = ots[i];
break;
}
}
// Find new Tool
ITool newTool = null;
int pos = c_tool.getSelectionIndex();
if (pos < (c_tool.getItemCount() - 1))
newTool = v_tools[pos];
// May be we've seleceted the same tool
if (newTool == null && oldTool == null)
return; // nothing to change
if (newTool != null && newTool.matches(oldTool))
return; // nothing to change
// Apply changes
fim.changeProjectTools(oldTool, newTool);
apply();
updateData();
}
/**
* Opens Tools selection dialog.
* Depending of result (OK/Cancel)
* either applies tools changes,
* or re-creates modification to abandon changes
*/
private void modifyTools() {
ToolSelectionDialog d = new ToolSelectionDialog(usercomp.getShell(), ri);
d.all = v_tools;
d.fi = (IFolderInfo)ri;
d.mod = mod;
int result = d.open();
if (d.removed.size() > 0 || d.added.size() > 0) {
if (result == 0) {
apply();
updateData();
} else {
mod = getModification(); // re-read data
}
}
}
/**
* Applies changes to Modification
*/
private void apply() {
try {
mod.apply();
} catch (CoreException e) {
ManagedBuilderUIPlugin.log(e);
}
}
private void modifyToolchain() {
IFolderInfoModification foim = (IFolderInfoModification)mod;
int x = c_toolchain.getSelectionIndex();
if (NO_TC.equals(c_toolchain.getItem(x))) {
foim.setToolChain(null);
} else {
IToolChain tc = v_tcs[x];
if (tc == null) return;
foim.setToolChain(tc);
}
apply();
updateData();
}
public static Image getErrorIcon(IStatus st) {
if (st.isOK())
return null;
int sev = st.getSeverity();
if (sev == IStatus.ERROR)
return IMG_ERROR;
else if (sev == IStatus.WARNING)
return IMG_WARNING;
else
return IMG_INFO;
}
private void modifyBuilder() {
IConfigurationModification cm = (IConfigurationModification)mod;
cm.setBuilder(v_bs[c_builder.getSelectionIndex()]);
apply();
updateData();
}
/**
* Forms a message containing
* @param cs
* @return
*/
public static String getCompatibilityMessage(CompatibilityStatus cs) {
IConflict[] cons = cs.getConflicts();
StringBuilder result = new StringBuilder();
for (int i=0; i<cons.length; i++) {
IBuildObject bo = cons[i].getBuildObject();
String n = (bo == null) ?
"NULL" : //$NON-NLS-1$
(bo instanceof ITool) ?
((ITool)bo).getUniqueRealName() :
bo.getName();
String t = EMPTY_STR;
switch (cons[i].getConflictType()) {
case IConflict.INCOMPATIBLE:
t = Messages.ToolChainEditTab_7;
break;
case IConflict.SOURCE_EXT_CONFLICT:
t = Messages.ToolChainEditTab_8;
break;
}
String o = EMPTY_STR;
switch (cons[i].getObjectType()) {
case IRealBuildObjectAssociation.OBJECT_TOOLCHAIN:
o = Messages.ToolChainEditTab_9;
break;
case IRealBuildObjectAssociation.OBJECT_BUILDER:
o = Messages.ToolChainEditTab_10;
break;
case IRealBuildObjectAssociation.OBJECT_CONFIGURATION:
o = Messages.ToolChainEditTab_11;
break;
case IRealBuildObjectAssociation.OBJECT_FILE_INFO:
o = Messages.ToolChainEditTab_12;
break;
case IRealBuildObjectAssociation.OBJECT_FOLDER_INFO:
o = Messages.ToolChainEditTab_13;
break;
case IRealBuildObjectAssociation.OBJECT_TOOL:
o = Messages.ToolChainEditTab_14;
break;
}
result.append(Messages.ToolChainEditTab_15)
.append(i+1).append(Messages.ToolChainEditTab_16)
.append(SPACE).append(t).append(SPACE).append(o).append(SPACE).append(n)
.append(Messages.ToolChainEditTab_17);
}
String s = result.toString();
if (s.trim().length() == 0)
s = cs.getMessage();
if (s == null)
s = EMPTY_STR;
return s;
}
}