/*******************************************************************************
* Copyright (c) 2004, 2010 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:
* QNX Software Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.dialogs.cpaths;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Preferences;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.cdt.core.model.CModelException;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.ICModelStatus;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.model.IPathEntry;
import org.eclipse.cdt.ui.dialogs.ICOptionContainer;
import org.eclipse.cdt.ui.dialogs.ICOptionPage;
import org.eclipse.cdt.ui.dialogs.TabFolderOptionBlock;
import org.eclipse.cdt.internal.ui.dialogs.IStatusChangeListener;
import org.eclipse.cdt.internal.ui.dialogs.StatusInfo;
import org.eclipse.cdt.internal.ui.dialogs.StatusUtil;
import org.eclipse.cdt.internal.ui.util.CoreUtility;
/**
* Abstract block for C/C++ Project Paths page for 3.X projects.
*
* @deprecated as of CDT 4.0. This option block was used to set preferences/properties
* for 3.X style projects.
*/
@Deprecated
abstract public class AbstractPathOptionBlock extends TabFolderOptionBlock implements ICOptionContainer {
private StatusInfo fCPathStatus;
private StatusInfo fBuildPathStatus;
private ICElement fCurrCElement;
private String fUserSettingsTimeStamp;
private long fFileTimeStamp;
private int fPageIndex, fPageCount;
private CPathBasePage fCurrPage;
private IStatusChangeListener fContext;
public AbstractPathOptionBlock(IStatusChangeListener context, int pageToShow) {
super(false);
fContext = context;
fPageIndex = pageToShow;
fCPathStatus = new StatusInfo();
fBuildPathStatus = new StatusInfo();
setOptionContainer(this);
}
// -------- public api --------
/**
* @return Returns the current class path (raw). Note that the entries
* returned must not be valid.
*/
public IPathEntry[] getRawCPath() throws CModelException{
List<CPElement> elements = getCPaths();
IPathEntry[] entries = getCProject().getRawPathEntries();
List<IPathEntry> cpath = new ArrayList<IPathEntry>(elements.size() + entries.length);
int[] applyTypes = getAppliedFilteredTypes();
// create and set the paths
for (int i = 0; i < elements.size(); i++) {
CPElement entry = (elements.get(i));
for (int applyType : applyTypes) {
if (entry.getEntryKind() == applyType) {
cpath.add(entry.getPathEntry());
break;
}
}
}
// add entries which do not match type being applyed by the ui block
for (IPathEntry entrie : entries) {
int pathType = entrie.getEntryKind();
boolean found = false;
for (int applyType : applyTypes) {
if (pathType == applyType) {
found = true;
break;
}
}
if (!found) {
cpath.add(entrie);
}
}
return cpath.toArray(new IPathEntry[cpath.size()]);
}
/**
* Initializes the paths for the given project. Multiple calls to init are
* allowed, but all existing settings will be cleared and replace by the
* given or default paths.
*
* @param element
* The C/C++ project to configure. Does not have to exist.
* @param cpathEntries
* The path entries to be set in the page. If <code>null</code> is
* passed, jdt default settings are used, or - if the project is an
* existing Java project - the path entries of the existing project
*/
public void init(ICElement element, IPathEntry[] cpathEntries) {
setCElement(element);
List<CPElement> newCPath = null;
if (cpathEntries == null) {
try {
cpathEntries = getCProject().getRawPathEntries();
} catch (CModelException e) {
}
}
if (cpathEntries != null) {
newCPath = getFilteredElements(cpathEntries, getFilteredTypes());
} else {
newCPath = new ArrayList<CPElement>();
}
initialize(element, newCPath);
}
abstract protected int[] getFilteredTypes(); // path type which block would like access to
abstract protected int[] getAppliedFilteredTypes(); // path type which block modifies
abstract protected void initialize(ICElement element, List<CPElement> cPaths);
protected ArrayList<CPElement> getFilteredElements(IPathEntry[] cPathEntries, int[] types) {
ArrayList<CPElement> newCPath = new ArrayList<CPElement>();
for (IPathEntry curr : cPathEntries) {
if (contains(types, curr.getEntryKind())) {
newCPath.add(CPElement.createFromExisting(curr, getCElement()));
}
}
return newCPath;
}
// returns true if set contains elem
private boolean contains(int[] set, int elem) {
if (set == null)
return false;
for (int i = 0; i < set.length; ++i) {
if (set[i] == elem)
return true;
}
return false;
}
abstract protected List<CPElement> getCPaths();
private String getEncodedSettings() {
StringBuffer buf = new StringBuffer();
List<CPElement> elements = getCPaths();
int nElements = elements.size();
buf.append('[').append(nElements).append(']');
for (int i = 0; i < nElements; i++) {
CPElement elem = elements.get(i);
elem.appendEncodedSettings(buf);
}
return buf.toString();
}
public boolean hasChangesInDialog() {
String currSettings = getEncodedSettings();
return !currSettings.equals(fUserSettingsTimeStamp);
}
public boolean hasChangesInCPathFile() {
IFile file = getProject().getFile(".cdtproject"); //$NON-NLS-1$
return fFileTimeStamp != file.getModificationStamp();
}
public void initializeTimeStamps() {
IFile file = getProject().getFile(".cdtproject"); //$NON-NLS-1$
fFileTimeStamp = file.getModificationStamp();
fUserSettingsTimeStamp = getEncodedSettings();
}
@Override
abstract protected void addTabs();
protected void setCElement(ICElement element) {
fCurrCElement = element;
}
protected ICElement getCElement() {
return fCurrCElement;
}
protected ICProject getCProject() {
return fCurrCElement.getCProject();
}
public IProject getProject() {
return getCProject().getProject();
}
protected void doStatusLineUpdate() {
IStatus res = findMostSevereStatus();
fContext.statusChanged(res);
}
private IStatus findMostSevereStatus() {
return StatusUtil.getMostSevere(new IStatus[] { fCPathStatus, fBuildPathStatus});
}
protected StatusInfo getPathStatus() {
return fCPathStatus;
}
// -------- tab switching ----------
@Override
public void setCurrentPage(ICOptionPage page) {
super.setCurrentPage(page);
CPathBasePage newPage = (CPathBasePage) page;
if (fCurrPage != null) {
List<?> selection = fCurrPage.getSelection();
if (!selection.isEmpty()) {
newPage.setSelection(selection);
}
}
fCurrPage = (CPathBasePage) page;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.cdt.ui.dialogs.ICOptionContainer#updateContainer()
*/
public void updateContainer() {
update();
}
protected void updateBuildPathStatus() {
List<CPElement> elements = getCPaths();
IPathEntry[] entries = new IPathEntry[elements.size()];
for (int i = elements.size() - 1; i >= 0; i--) {
CPElement currElement = elements.get(i);
entries[i] = currElement.getPathEntry();
}
ICModelStatus status = CoreModel.validatePathEntries(getCProject(), entries);
if (!status.isOK()) {
fBuildPathStatus.setError(status.getMessage());
return;
}
fBuildPathStatus.setOK();
}
public Preferences getPreferences() {
return null;
}
protected void addPage(CPathBasePage page) {
addTab(page);
if (fPageIndex == fPageCount) {
fCurrPage = page;
}
fPageCount++;
}
@Override
protected ICOptionPage getStartPage() {
if (fCurrPage == null) {
return super.getStartPage();
}
return fCurrPage;
}
protected void internalConfigureCProject(List<CPElement> cPathEntries, IProgressMonitor monitor) throws CoreException,
InterruptedException {
// 10 monitor steps to go
monitor.worked(2);
IPathEntry[] entries = getCProject().getRawPathEntries();
List<IPathEntry> cpath = new ArrayList<IPathEntry>(cPathEntries.size() + entries.length);
int[] applyTypes = getAppliedFilteredTypes();
// create and set the paths
for (int i = 0; i < cPathEntries.size(); i++) {
CPElement entry = (cPathEntries.get(i));
for (int applyType : applyTypes) {
if (entry.getEntryKind() == applyType) {
IResource res = entry.getResource();
if ((res instanceof IFolder) && !res.exists()) {
CoreUtility.createFolder((IFolder) res, true, true, null);
}
cpath.add(entry.getPathEntry());
break;
}
}
}
// add entries which do not match type being applyed by the ui block
for (IPathEntry entrie : entries) {
int pathType = entrie.getEntryKind();
boolean found = false;
for (int applyType : applyTypes) {
if (pathType == applyType) {
found = true;
break;
}
}
if (!found) {
cpath.add(entrie);
}
}
monitor.worked(1);
getCProject().setRawPathEntries(cpath.toArray(new IPathEntry[cpath.size()]),
new SubProgressMonitor(monitor, 7));
}
// -------- creation -------------------------------
public void configureCProject(IProgressMonitor monitor) throws CoreException, InterruptedException {
if (monitor == null) {
monitor = new NullProgressMonitor();
}
monitor.setTaskName(CPathEntryMessages.CPathsBlock_operationdesc_c);
monitor.beginTask("", 10); //$NON-NLS-1$
try {
internalConfigureCProject(getCPaths(), monitor);
initializeTimeStamps();
} finally {
monitor.done();
}
}
}