/*******************************************************************************
* Copyright (c) 2007, 2010 Intel Corporation, QNX Software Systems, 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
* Miwako Tokugawa (Intel Corporation) - Fixed-location tooltip support
* QNX Software Systems - [269571] Apply button failure on tool changes
*******************************************************************************/
package org.eclipse.cdt.managedbuilder.ui.properties;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.cdt.core.settings.model.ICResourceDescription;
import org.eclipse.cdt.managedbuilder.core.BuildException;
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.IHoldsOptions;
import org.eclipse.cdt.managedbuilder.core.IOption;
import org.eclipse.cdt.managedbuilder.core.IOptionCategory;
import org.eclipse.cdt.managedbuilder.core.IResourceConfiguration;
import org.eclipse.cdt.managedbuilder.core.IResourceInfo;
import org.eclipse.cdt.managedbuilder.core.ITool;
import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;
import org.eclipse.cdt.managedbuilder.internal.core.MultiConfiguration;
import org.eclipse.cdt.managedbuilder.internal.macros.BuildMacroProvider;
import org.eclipse.cdt.managedbuilder.internal.ui.Messages;
import org.eclipse.cdt.ui.newui.CDTPrefUtil;
import org.eclipse.cdt.ui.newui.PageLayout;
import org.eclipse.core.resources.IResource;
import org.eclipse.jface.preference.IPreferencePageContainer;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.ScrollBar;
/**
* Tool Settings Tab in project properties Build Settings
*
* @noextend This class is not intended to be subclassed by clients.
* @noinstantiate This class is not intended to be instantiated by clients.
*/
public class ToolSettingsTab extends AbstractCBuildPropertyTab implements IPreferencePageContainer {
private static ToolListElement selectedElement;
/*
* Dialog widgets
*/
private TreeViewer optionList;
private StyledText tipText;
private StyleRange styleRange;
private SashForm sashForm;
private SashForm sashForm2;
private Composite settingsPageContainer;
private ScrolledComposite containerSC;
/*
* Bookeeping variables
*/
private Map<String, List<AbstractToolSettingUI>> configToPageListMap;
private IPreferenceStore settingsStore;
private AbstractToolSettingUI currentSettingsPage;
private ToolListContentProvider listprovider;
private Object propertyObject;
private IResourceInfo fInfo;
private boolean displayFixedTip = CDTPrefUtil.getBool(CDTPrefUtil.KEY_TIPBOX);
private int[] defaultWeights = new int[] {4, 1};
private int[] hideTipBoxWeights = new int[] {1, 0};
@Override
public void createControls(Composite par) {
super.createControls(par);
usercomp.setLayout(new GridLayout());
configToPageListMap = new HashMap<String, List<AbstractToolSettingUI>>();
settingsStore = ToolSettingsPrefStore.getDefault();
// Create the sash form
sashForm = new SashForm(usercomp, SWT.NONE);
sashForm.setOrientation(SWT.HORIZONTAL);
sashForm.setLayoutData(new GridData(GridData.FILL_BOTH));
GridLayout layout = new GridLayout();
layout.numColumns = 2;
layout.marginHeight = 5;
sashForm.setLayout(layout);
if (displayFixedTip==false) {
createSelectionArea(sashForm);
createEditArea(sashForm);
} else {
createSelectionArea(sashForm);
sashForm2 = new SashForm(sashForm, SWT.NONE);
sashForm2.setOrientation(SWT.VERTICAL);
createEditArea(sashForm2);
createTipArea(sashForm2);
sashForm2.setWeights(defaultWeights);
}
usercomp.addControlListener(new ControlAdapter() {
@Override
public void controlResized(ControlEvent e) {
specificResize();
}});
propertyObject = page.getElement();
setValues();
specificResize();
}
private void specificResize() {
Point p1 = optionList.getTree().computeSize(SWT.DEFAULT, SWT.DEFAULT);
Point p2 = optionList.getTree().getSize();
Point p3 = usercomp.getSize();
p1.x += calcExtra();
if (p3.x >= p1.x && (p1.x < p2.x || (p2.x * 2 < p3.x))) {
optionList.getTree().setSize(p1.x , p2.y);
sashForm.setWeights(new int[] {p1.x, (p3.x - p1.x)});
}
}
private int calcExtra() {
int x = optionList.getTree().getBorderWidth() * 2;
ScrollBar sb = optionList.getTree().getVerticalBar();
if (sb != null && sb.isVisible()) x += sb.getSize().x;
return x;
}
protected void createSelectionArea (Composite parent) {
optionList = new TreeViewer(parent, SWT.SINGLE|SWT.H_SCROLL|SWT.V_SCROLL|SWT.BORDER);
optionList.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
handleOptionSelection();
}});
optionList.getControl().setLayoutData(new GridData(GridData.FILL_BOTH));
optionList.setLabelProvider(new ToolListLabelProvider());
optionList.addFilter(new ViewerFilter() {
@Override
public boolean select(Viewer viewer,
Object parent,
Object element) {
if(parent instanceof IResourceConfiguration && element instanceof ITool) {
return !((ITool)element).getCustomBuildStep();
} else {
return true;
}
}
});
}
/**
* @param name - header of the tooltip help
* @param tip - tooltip text
* @since 7.0
*/
protected void updateTipText(String name, String tip) {
if (tipText==null) {
return;
}
tipText.setText(name+"\n\n"+tip); //$NON-NLS-1$
styleRange.length = name.length();
tipText.setStyleRange(styleRange);
tipText.update();
}
/* (non-Javadoc)
* Method resetTipText
* @since 7.0
*/
private void resetTipText() {
if (tipText==null) {
return;
}
tipText.setText(Messages.ToolSettingsTab_0);
tipText.update();
}
/* (non-Javadoc)
* Method displayOptionsForCategory
* @param category
*/
private void displayOptionsForCategory(ToolListElement toolListElement) {
selectedElement = toolListElement;
IOptionCategory category = toolListElement.getOptionCategory();
IHoldsOptions optionHolder = toolListElement.getHoldOptions();
AbstractToolSettingUI oldPage = currentSettingsPage;
currentSettingsPage = null;
// Create a new settings page if necessary
List<AbstractToolSettingUI> pages = getPagesForConfig();
for (AbstractToolSettingUI page : pages) {
if (page.isFor(optionHolder, category)) {
currentSettingsPage = page;
break;
}
}
if (currentSettingsPage == null) {
currentSettingsPage = new BuildOptionSettingsUI(
this,
fInfo,
optionHolder,
category,
displayFixedTip);
boolean needToolTipBox = false;
if (displayFixedTip==true) {
needToolTipBox = ((BuildOptionSettingsUI)currentSettingsPage).needToolTipBox(optionHolder,category);
}
pages.add(currentSettingsPage);
currentSettingsPage.setContainer(this);
currentSettingsPage.setToolTipBoxNeeded(needToolTipBox);
if (currentSettingsPage.getControl() == null) {
currentSettingsPage.createControl(settingsPageContainer);
}
}
// Make all the other pages invisible
Control[] children = settingsPageContainer.getChildren();
Control currentControl = currentSettingsPage.getControl();
for (Control element : children) {
if (element != currentControl)
element.setVisible(false);
}
if (displayFixedTip==true) {
if (currentSettingsPage.isToolTipBoxNeeded()==false) {
// eliminate the option tip box
sashForm2.setWeights(hideTipBoxWeights);
sashForm2.layout();
} else {
// display the option tip box
sashForm2.setWeights(defaultWeights);
sashForm2.layout();
}
}
currentSettingsPage.setVisible(true);
currentSettingsPage.updateFields();
if (oldPage != null && oldPage != currentSettingsPage) {
oldPage.setVisible(false);
resetTipText();
}
// Set the size of the scrolled area
containerSC.setMinSize(currentSettingsPage.computeSize());
settingsPageContainer.layout();
}
/* (non-Javadoc)
* Method displayOptionsForTool
* @param tool
*/
private void displayOptionsForTool(ToolListElement toolListElement) {
selectedElement = toolListElement;
ITool tool = toolListElement.getTool();
// Cache the current build setting page
AbstractToolSettingUI oldPage = currentSettingsPage;
currentSettingsPage = null;
// Create a new page if we need one
List<AbstractToolSettingUI> pages = getPagesForConfig();
for (AbstractToolSettingUI page : pages) {
if (page.isFor(tool, null)) {
currentSettingsPage = page;
break;
}
}
if (currentSettingsPage == null) {
currentSettingsPage = new BuildToolSettingUI(this, fInfo, tool);
pages.add(currentSettingsPage);
currentSettingsPage.setContainer(this);
if (currentSettingsPage.getControl() == null) {
currentSettingsPage.createControl(settingsPageContainer);
}
}
// Make all the other pages invisible
Control[] children = settingsPageContainer.getChildren();
Control currentControl = currentSettingsPage.getControl();
for (Control element : children) {
if (element != currentControl)
element.setVisible(false);
}
if (displayFixedTip==true) {
// eliminate the tool tip area
sashForm2.setWeights(hideTipBoxWeights);
sashForm2.layout();
}
// Make the current page visible
currentSettingsPage.setVisible(true);
// Save the last page build options.
if (oldPage != null && oldPage != currentSettingsPage){
oldPage.storeSettings();
}
currentSettingsPage.setValues();
if (oldPage != null && oldPage != currentSettingsPage)
oldPage.setVisible(false);
// Set the size of the scrolled area
containerSC.setMinSize(currentSettingsPage.computeSize());
settingsPageContainer.layout();
}
/* (non-Javadoc)
* Add the fixed-location tool tip box.
*/
private void createTipArea (Composite parent) {
tipText = new StyledText(parent, SWT.V_SCROLL|SWT.BORDER | SWT.READ_ONLY | SWT.MULTI | SWT.WRAP);
tipText.setLayoutData(new GridData(GridData.FILL_BOTH));
tipText.setText(Messages.ToolSettingsTab_0);
styleRange = new StyleRange();
styleRange.start = 0;
FontData data = new FontData();
data.setHeight(10);
//data.setName("sans");
data.setStyle(SWT.BOLD);
Font font = new Font(parent.getDisplay(),data);
styleRange.font = font;
}
/* (non-Javadoc)
* Add the tabs relevant to the project to edit area tab folder.
*/
protected void createEditArea(Composite parent) {
int style = (SWT.H_SCROLL | SWT.V_SCROLL);
if (displayFixedTip) {
style |= SWT.BORDER;
}
containerSC = new ScrolledComposite(parent, style);
containerSC.setExpandHorizontal(true);
containerSC.setExpandVertical(true);
// Add a container for the build settings page
settingsPageContainer = new Composite(containerSC, SWT.NULL);
settingsPageContainer.setLayout(new PageLayout());
containerSC.setContent(settingsPageContainer);
containerSC.setMinSize(settingsPageContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT));
settingsPageContainer.layout();
}
@Override
public void setVisible(boolean visible){
if(visible){
updateData(page.getResDesc());
}
super.setVisible(visible);
}
protected void setValues() {
/*
* This method updates the context of the build property pages
* - Which configuration/resource configuration is selected
* - Which tool/option category is selected
*
* It is called:
* - When a property page becomes visible
* - When the user changes the configuration selection
* - When the user changes the "exclude" setting for a resource
*/
// Create the Tree Viewer content provider if first time
if (listprovider == null) {
IResource resource = (IResource) propertyObject;
listprovider = new ToolListContentProvider(resource.getType());
optionList.setContentProvider(listprovider);
}
// Update the selected configuration and the Tree Viewer
ToolListElement[] newElements;
optionList.setInput(fInfo);
newElements = (ToolListElement[])listprovider.getElements(fInfo);
optionList.expandAll();
// Determine what the selection in the tree should be
// If the saved selection is not null, try to match the saved selection
// with an object in the new element list.
// Otherwise, select the first tool in the tree
Object primaryObject = null;
if (selectedElement != null && newElements != null) {
selectedElement = matchSelectionElement(selectedElement, newElements);
}
if (selectedElement == null) {
selectedElement = (newElements != null && newElements.length > 0 ? newElements[0] : null);
}
if (selectedElement != null) {
primaryObject = selectedElement.getTool();
if (primaryObject == null) {
primaryObject = selectedElement.getOptionCategory();
}
if (primaryObject != null) {
if (primaryObject instanceof IOptionCategory) {
((ToolSettingsPrefStore)settingsStore).setSelection(getResDesc(), selectedElement, (IOptionCategory)primaryObject);
}
optionList.setSelection(new StructuredSelection(selectedElement), true);
}
}
}
private ToolListElement matchSelectionElement(ToolListElement currentElement, ToolListElement[] elements) {
// First, look for an exact match
ToolListElement match = exactMatchSelectionElement(currentElement, elements);
if (match == null)
// Else, look for the same tool/category in the new set of elements
match = equivalentMatchSelectionElement(currentElement, elements);
return match;
}
private ToolListElement exactMatchSelectionElement(ToolListElement currentElement, ToolListElement[] elements) {
for (ToolListElement e : elements) {
if (e == currentElement) {
return currentElement;
}
e = exactMatchSelectionElement(currentElement, e.getChildElements());
if (e != null) return e;
}
return null;
}
private ToolListElement equivalentMatchSelectionElement(ToolListElement currentElement, ToolListElement[] elements) {
for (ToolListElement e : elements) {
if (e.isEquivalentTo(currentElement)) {
return e;
}
e = equivalentMatchSelectionElement(currentElement, e.getChildElements());
if (e != null) return e;
}
return null;
}
private void handleOptionSelection() {
// Get the selection from the tree list
if (optionList == null) return;
IStructuredSelection selection = (IStructuredSelection) optionList.getSelection();
// Set the option page based on the selection
ToolListElement toolListElement = (ToolListElement)selection.getFirstElement();
if (toolListElement != null) {
IOptionCategory cat = toolListElement.getOptionCategory();
if (cat == null)
cat = (IOptionCategory)toolListElement.getTool();
if (cat != null)
((ToolSettingsPrefStore)settingsStore).setSelection(getResDesc(), toolListElement, cat);
cat = toolListElement.getOptionCategory();
if (cat != null) {
displayOptionsForCategory(toolListElement);
} else {
displayOptionsForTool(toolListElement);
}
}
}
/*
* (non-Javadoc)
* @see org.eclipse.cdt.ui.dialogs.ICOptionPage#performDefaults()
*/
@Override
protected void performDefaults() {
if (page.isForProject()) {
ManagedBuildManager.resetConfiguration(page.getProject(), getCfg());
} else {
ManagedBuildManager.resetOptionSettings(fInfo);
}
ITool tools[];
if (page.isForProject())
tools = getCfg().getFilteredTools();
else
tools = getResCfg(getResDesc()).getTools();
for( int i = 0; i < tools.length; i++ ){
if(!tools[i].getCustomBuildStep()) {
tools[i].setToolCommand(null);
tools[i].setCommandLinePattern(null);
}
}
// Reset the category or tool selection and run selection event handler
selectedElement = null;
setDirty(true);
fInfo = getResCfg(getResDesc());
setValues();
handleOptionSelection();
}
/*
* (non-Javadoc)
* @see org.eclipse.cdt.ui.dialogs.ICOptionPage#performApply(IProgressMonitor)
*/
private void copyHoldsOptions(IHoldsOptions src, IHoldsOptions dst, IResourceInfo res){
if(src instanceof ITool) {
ITool t1 = (ITool)src;
ITool t2 = (ITool)dst;
if (t1.getCustomBuildStep()) return;
t2.setToolCommand(t1.getToolCommand());
t2.setCommandLinePattern(t1.getCommandLinePattern());
}
IOption op1[] = src.getOptions();
IOption op2[] = dst.getOptions();
for(int i = 0; i < op1.length; i++) {
setOption(op1[i], op2[i], dst, res);
}
}
/**
* @param filter - a viewer filter
* @see StructuredViewer#addFilter(ViewerFilter)
*
* @since 5.1
*/
protected void addFilter(ViewerFilter filter) {
optionList.addFilter(filter);
}
/**
* Copy the value of an option to another option for a given resource.
* @param op1 - option to copy the value from
* @param op2 - option to copy the value to
* @param dst - the holder/parent of the option
* @param res - the resource configuration the option belongs to
*
* @since 5.1
*/
protected void setOption(IOption op1, IOption op2, IHoldsOptions dst, IResourceInfo res){
try {
switch (op1.getValueType()) {
case IOption.BOOLEAN :
boolean boolVal = op1.getBooleanValue();
ManagedBuildManager.setOption(res, dst, op2, boolVal);
break;
case IOption.ENUMERATED :
String enumVal = op1.getStringValue();
String enumId = op1.getEnumeratedId(enumVal);
String out = (enumId != null && enumId.length() > 0) ? enumId : enumVal;
ManagedBuildManager.setOption(res, dst, op2, out);
break;
case IOption.STRING :
ManagedBuildManager.setOption(res, dst, op2, op1.getStringValue());
break;
case IOption.STRING_LIST :
case IOption.INCLUDE_PATH :
case IOption.PREPROCESSOR_SYMBOLS :
case IOption.LIBRARIES :
case IOption.OBJECTS :
case IOption.INCLUDE_FILES:
case IOption.LIBRARY_PATHS:
case IOption.LIBRARY_FILES:
case IOption.MACRO_FILES:
case IOption.UNDEF_INCLUDE_PATH:
case IOption.UNDEF_PREPROCESSOR_SYMBOLS:
case IOption.UNDEF_INCLUDE_FILES:
case IOption.UNDEF_LIBRARY_PATHS:
case IOption.UNDEF_LIBRARY_FILES:
case IOption.UNDEF_MACRO_FILES:
@SuppressWarnings("unchecked")
String[] data = ((List<String>)op1.getValue()).toArray(new String[0]);
ManagedBuildManager.setOption(res, dst, op2, data);
break;
default :
break;
}
} catch (BuildException e) {
} catch (ClassCastException e) {
}
}
protected boolean containsDefaults(){
IConfiguration parentCfg = fInfo.getParent().getParent();
ITool tools[] = fInfo.getParent().getTools();
for (ITool tool : tools) {
if(!tool.getCustomBuildStep()){
ITool cfgTool = parentCfg.getToolChain().getTool(tool.getSuperClass().getId());
// Check for a non-default command or command-line-pattern
if(cfgTool != null){
if (!(tool.getToolCommand().equals(cfgTool.getToolCommand()))) return false;
if (!(tool.getCommandLinePattern().equals(cfgTool.getCommandLinePattern()))) return false;
}
// Check for a non-default option
IOption options[] = tool.getOptions();
for (IOption option : options) {
if(option.getParent() == tool){
IOption ext = option;
do{
if(ext.isExtensionElement())
break;
} while((ext = ext.getSuperClass()) != null);
if(ext != null){
if(cfgTool != null){
IOption defaultOpt = cfgTool.getOptionBySuperClassId(ext.getId());
try {
if(defaultOpt != null && defaultOpt.getValueType() == option.getValueType()){
Object value = option.getValue();
Object defaultVal = defaultOpt.getValue();
if(value.equals(defaultVal))
continue;
//TODO: check list also
}
}catch (BuildException e) {
}
}
}
return false;
}
}
}
}
return true;
}
/* (non-Javadoc)
* Answers the list of settings pages for the selected configuration
*/
private List<AbstractToolSettingUI> getPagesForConfig() {
if (getCfg() == null) return null;
List<AbstractToolSettingUI> pages = configToPageListMap.get(getCfg().getId());
if (pages == null) {
pages = new ArrayList<AbstractToolSettingUI>();
configToPageListMap.put(getCfg().getId(), pages);
}
return pages;
}
public IPreferenceStore getPreferenceStore() {
return settingsStore;
}
/**
* Sets the "dirty" state
* @param b - the new dirty state, {@code true} or {@code false}
*/
public void setDirty(boolean b) {
List<AbstractToolSettingUI> pages = getPagesForConfig();
if (pages == null)
return;
for (AbstractToolSettingUI page : pages) {
if (page == null)
continue;
page.setDirty(b);
}
}
/**
* @return the "dirty" state
*/
public boolean isDirty() {
// Check each settings page
List<AbstractToolSettingUI> pages = getPagesForConfig();
// Make sure we have something to work on
if (pages == null) {
// Nothing to do
return false;
}
for (AbstractToolSettingUI page : pages) {
if (page == null) continue;
if (page.isDirty()) return true;
}
return false;
}
/**
* @return the build macro provider to be used for macro resolution
* In case the "Build Macros" tab is available, returns the BuildMacroProvider
* supplied by that tab.
* Unlike the default provider, that provider also contains
* the user-modified macros that are not applied yet
* If the "Build Macros" tab is not available, returns the default BuildMacroProvider
*
* @noreference This method is not intended to be referenced by clients.
*/
public BuildMacroProvider obtainMacroProvider(){
return (BuildMacroProvider)ManagedBuildManager.getBuildMacroProvider();
}
@Override
public void updateData(ICResourceDescription cfgd) {
fInfo = getResCfg(cfgd);
setValues();
specificResize();
handleOptionSelection();
}
@Override
protected void performApply(ICResourceDescription src, ICResourceDescription dst) {
IResourceInfo ri1 = getResCfg(src);
IResourceInfo ri2 = getResCfg(dst);
copyHoldsOptions(ri1.getParent().getToolChain(), ri2.getParent().getToolChain(), ri2);
ITool[] t1, t2;
if (ri1 instanceof IFolderInfo){
t1 = ((IFolderInfo)ri1).getFilteredTools();
t2 = ((IFolderInfo)ri2).getFilteredTools();
} else if (ri1 instanceof IFileInfo) {
t1 = ((IFileInfo)ri1).getToolsToInvoke();
t2 = ((IFileInfo)ri2).getToolsToInvoke();
} else return;
// get the corresponding pairs of tools for which we can copy settings
// and do the copy
for (Map.Entry<ITool, ITool> pair : getToolCorrespondence(t1, t2).entrySet()) {
copyHoldsOptions(pair.getKey(), pair.getValue(), ri2);
}
setDirty(false);
updateData(getResDesc());
}
/**
* Computes the correspondence of tools in the copy-from set (<tt>t1</tt>) and the
* copy-to set (<tt>t2</tt>) in an apply operation. The resulting pairs are in the order
* of the <tt>t2</tt> array. Note that tools that have no correspondence do not appear in
* the result, and that order is not significant. Also, in case of replication of tools
* in a chain (?) they are matched one-for one in the order in which they are found in
* each chain.
*
* @param t1 - first group of tools. May not be <code>null</code>
* @param t2 - second group of tools. May not be <code>null</code>
* @return the one-for-one correspondence of tools, in order of <tt>t2</tt>
*/
private Map<ITool, ITool> getToolCorrespondence(ITool[] t1, ITool[] t2) {
Map<ITool, ITool> result = new java.util.LinkedHashMap<ITool, ITool>();
Map<ITool, List<ITool>> realT1Tools = new java.util.LinkedHashMap<ITool, List<ITool>>();
for (ITool next : t1) {
ITool real = ManagedBuildManager.getRealTool(next);
List<ITool> list = realT1Tools.get(real);
if (list == null) {
// the immutable singleton list is efficient in storage
realT1Tools.put(real, Collections.singletonList(next));
} else {
if (list.size() == 1) {
// make the list mutable
list = new java.util.ArrayList<ITool>(list);
realT1Tools.put(real, list);
}
list.add(next);
}
}
for (ITool next : t2) {
ITool real = ManagedBuildManager.getRealTool(next);
List<ITool> correspondents = realT1Tools.get(real);
if (correspondents != null) {
result.put(correspondents.get(0), next);
// consume the correspondent
if (correspondents.size() == 1) {
// remove the list; no more entries to consume
realT1Tools.remove(real);
} else {
// cost of removal in array-list is not a concern
// considering that this is a UI Apply button and
// replication of tools is a fringe case
correspondents.remove(0);
}
}
}
return result;
}
// IPreferencePageContainer methods
@Override
public void updateButtons() {}
public void updateMessage() {}
public void updateTitle() {}
@Override
public boolean canBeVisible() {
IConfiguration cfg = getCfg();
if (cfg instanceof MultiConfiguration)
return ((MultiConfiguration)cfg).isManagedBuildOn();
else
return cfg.getBuilder().isManagedBuildOn();
}
}