| /******************************************************************************* |
| * Copyright (c) 2004, 2016 QNX Software Systems and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * QNX Software Systems - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.cdt.internal.ui.dialogs.cpaths; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.List; |
| |
| import org.eclipse.cdt.core.model.CoreModel; |
| import org.eclipse.cdt.core.model.CoreModelUtil; |
| import org.eclipse.cdt.core.model.ICContainer; |
| import org.eclipse.cdt.core.model.ICElement; |
| import org.eclipse.cdt.core.model.ICProject; |
| import org.eclipse.cdt.core.model.IContainerEntry; |
| import org.eclipse.cdt.core.model.IIncludeEntry; |
| import org.eclipse.cdt.core.model.IMacroEntry; |
| import org.eclipse.cdt.core.model.IPathEntry; |
| import org.eclipse.cdt.core.model.ITranslationUnit; |
| import org.eclipse.cdt.internal.ui.ICHelpContextIds; |
| import org.eclipse.cdt.internal.ui.dialogs.IStatusChangeListener; |
| import org.eclipse.cdt.internal.ui.dialogs.TypedElementSelectionValidator; |
| import org.eclipse.cdt.internal.ui.dialogs.TypedViewerFilter; |
| import org.eclipse.cdt.internal.ui.wizards.dialogfields.DialogField; |
| import org.eclipse.cdt.internal.ui.wizards.dialogfields.IDialogFieldListener; |
| import org.eclipse.cdt.internal.ui.wizards.dialogfields.ITreeListAdapter; |
| import org.eclipse.cdt.internal.ui.wizards.dialogfields.LayoutUtil; |
| import org.eclipse.cdt.internal.ui.wizards.dialogfields.SelectionButtonDialogField; |
| import org.eclipse.cdt.internal.ui.wizards.dialogfields.TreeListDialogField; |
| import org.eclipse.cdt.ui.CDTSharedImages; |
| import org.eclipse.cdt.ui.CElementContentProvider; |
| import org.eclipse.cdt.ui.CUIPlugin; |
| import org.eclipse.core.resources.IContainer; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.jface.dialogs.IInputValidator; |
| import org.eclipse.jface.dialogs.InputDialog; |
| import org.eclipse.jface.layout.PixelConverter; |
| import org.eclipse.jface.viewers.StructuredSelection; |
| import org.eclipse.jface.viewers.ViewerFilter; |
| import org.eclipse.jface.window.Window; |
| import org.eclipse.osgi.util.NLS; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.KeyEvent; |
| import org.eclipse.swt.events.SelectionAdapter; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.widgets.Button; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.DirectoryDialog; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.dialogs.ElementTreeSelectionDialog; |
| import org.eclipse.ui.model.WorkbenchLabelProvider; |
| |
| /** |
| * DialogPage for C/C++ Project Paths page for 3.X projects. |
| */ |
| public class CPathIncludeSymbolEntryPage extends CPathIncludeSymbolEntryBasePage { |
| private TreeListDialogField<CPElementGroup> fIncludeSymPathsList; |
| private SelectionButtonDialogField fShowInheritedPaths; |
| private ICProject fCurrCProject; |
| private CPElementFilter fFilter; |
| private IStatusChangeListener fContext; |
| |
| private final int IDX_ADD_FOLDER_FILE = 0; |
| private final int IDX_ADD_SYMBOL = 2; |
| private final int IDX_ADD_EXT_INCLUDE = 4; |
| private final int IDX_ADD_WS_INCLUDE = 5; |
| private final int IDX_ADD_CONTRIBUTED = 7; |
| private final int IDX_EDIT = 9; |
| private final int IDX_REMOVE = 10; |
| private final int IDX_EXPORT = 12; |
| private final int IDX_UP = 14; |
| private final int IDX_DOWN = 15; |
| |
| private static final String[] buttonLabel = new String[] { |
| |
| CPathEntryMessages.IncludeSymbolEntryPage_addFolderFile, null, |
| CPathEntryMessages.IncludeSymbolEntryPage_addUserSymbol, null, |
| CPathEntryMessages.IncludeSymbolEntryPage_addExternalInclude, |
| CPathEntryMessages.IncludeSymbolEntryPage_addFromWorkspace, null, |
| CPathEntryMessages.IncludeSymbolEntryPage_addContributed, null, |
| CPathEntryMessages.IncludeSymbolEntryPage_edit, CPathEntryMessages.IncludeSymbolEntryPage_remove, null, |
| CPathEntryMessages.IncludeSymbolEntryPage_export, null, CPathEntryMessages.IncludeSymbolEntryPage_up, |
| CPathEntryMessages.IncludeSymbolEntryPage_down }; |
| private CPElementGroup fTopGroup; |
| |
| private class IncludeSymbolAdapter implements IDialogFieldListener, ITreeListAdapter<CPElementGroup> { |
| private final Object[] EMPTY_ARR = new Object[0]; |
| |
| // -------- IListAdapter -------- |
| @Override |
| public void customButtonPressed(TreeListDialogField<CPElementGroup> field, int index) { |
| ListCustomButtonPressed(field, index); |
| } |
| |
| @Override |
| public void selectionChanged(TreeListDialogField<CPElementGroup> field) { |
| listPageSelectionChanged(field); |
| } |
| |
| @Override |
| public void doubleClicked(TreeListDialogField<CPElementGroup> field) { |
| ListPageDoubleClicked(field); |
| } |
| |
| @Override |
| public void keyPressed(TreeListDialogField<CPElementGroup> field, KeyEvent event) { |
| ListPageKeyPressed(field, event); |
| } |
| |
| @Override |
| public Object[] getChildren(TreeListDialogField<CPElementGroup> field, Object element) { |
| if (element instanceof CPElement) { |
| return ((CPElement) element).getChildren(); |
| } else if (element instanceof CPElementGroup) { |
| return ((CPElementGroup) element).getChildren(); |
| } |
| return EMPTY_ARR; |
| } |
| |
| @Override |
| public Object getParent(TreeListDialogField<CPElementGroup> field, Object element) { |
| if (element instanceof CPElementGroup) { |
| return ((CPElementGroup) element).getParent(); |
| } else if (element instanceof CPElement) { |
| return ((CPElement) element).getParent(); |
| } |
| return null; |
| } |
| |
| @Override |
| public boolean hasChildren(TreeListDialogField<CPElementGroup> field, Object element) { |
| if (element instanceof CPElementGroup) { |
| return true; |
| } |
| if (element instanceof CPElement) { |
| return ((CPElement) element).getChildren().length > 0; |
| } |
| return false; |
| } |
| |
| // ---------- IDialogFieldListener -------- |
| |
| @Override |
| public void dialogFieldChanged(DialogField field) { |
| listPageDialogFieldChanged(field); |
| } |
| |
| } |
| |
| public CPathIncludeSymbolEntryPage(IStatusChangeListener context) { |
| super(CPathEntryMessages.IncludeSymbolEntryPage_title); |
| fContext = context; |
| IncludeSymbolAdapter adapter = new IncludeSymbolAdapter(); |
| fIncludeSymPathsList = new TreeListDialogField<>(adapter, buttonLabel, |
| new CPElementLabelProvider(true, false)) { |
| |
| @Override |
| protected int getTreeStyle() { |
| return super.getTreeStyle() & ~SWT.MULTI; |
| } |
| }; |
| fIncludeSymPathsList.setLabelText(CPathEntryMessages.IncludeSymbolEntryPage_label); |
| fIncludeSymPathsList.enableButton(IDX_REMOVE, false); |
| fIncludeSymPathsList.enableButton(IDX_EDIT, false); |
| fIncludeSymPathsList.enableButton(IDX_ADD_CONTRIBUTED, true); |
| fIncludeSymPathsList.enableButton(IDX_ADD_EXT_INCLUDE, true); |
| fIncludeSymPathsList.enableButton(IDX_ADD_WS_INCLUDE, true); |
| fIncludeSymPathsList.enableButton(IDX_ADD_SYMBOL, true); |
| fIncludeSymPathsList.enableButton(IDX_EXPORT, false); |
| fIncludeSymPathsList.enableButton(IDX_UP, false); |
| fIncludeSymPathsList.enableButton(IDX_DOWN, false); |
| fIncludeSymPathsList.setTreeExpansionLevel(2); |
| fShowInheritedPaths = new SelectionButtonDialogField(SWT.CHECK); |
| fShowInheritedPaths.setSelection(true); |
| fShowInheritedPaths.setLabelText(CPathEntryMessages.IncludeSymbolsEntryPage_show_inherited_check); |
| fShowInheritedPaths.setDialogFieldListener(adapter); |
| |
| fFilter = new CPElementFilter( |
| new int[] { -1, IPathEntry.CDT_INCLUDE, IPathEntry.CDT_MACRO, IPathEntry.CDT_CONTAINER }, false, true); |
| } |
| |
| @Override |
| public void createControl(Composite parent) { |
| PixelConverter converter = new PixelConverter(parent); |
| |
| Composite composite = new Composite(parent, SWT.NONE); |
| composite.setLayoutData(new GridData(GridData.FILL_BOTH)); |
| |
| LayoutUtil.doDefaultLayout(composite, new DialogField[] { fIncludeSymPathsList, fShowInheritedPaths }, true); |
| LayoutUtil.setHorizontalGrabbing(fIncludeSymPathsList.getTreeControl(null), true); |
| |
| int buttonBarWidth = converter.convertWidthInCharsToPixels(24); |
| fIncludeSymPathsList.setButtonsMinWidth(buttonBarWidth); |
| setControl(composite); |
| fIncludeSymPathsList.getTreeViewer().addFilter(fFilter); |
| PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, ICHelpContextIds.PROJECT_INCLUDE_PATHS_SYMBOLS); |
| } |
| |
| @Override |
| public Image getImage() { |
| return CDTSharedImages.getImage(CDTSharedImages.IMG_OBJS_INCLUDES_CONTAINER); |
| } |
| |
| @Override |
| public void init(ICElement cElement, List<CPElement> cPaths) { |
| fCurrCProject = cElement.getCProject(); |
| List<CPElementGroup> elements = createGroups(cElement, cPaths); |
| fIncludeSymPathsList.setElements(elements); |
| updateStatus(); |
| } |
| |
| private void updateStatus() { |
| CPElement entryError = null; |
| int nErrorEntries = 0; |
| IStatus status = Status.OK_STATUS; |
| List<CPElement> elements = getCPaths(); |
| for (int i = elements.size() - 1; i >= 0; i--) { |
| CPElement currElement = elements.get(i); |
| if (currElement.getStatus().getSeverity() != IStatus.OK) { |
| nErrorEntries++; |
| if (entryError == null) { |
| entryError = currElement; |
| } |
| } |
| } |
| |
| if (nErrorEntries > 0) { |
| if (nErrorEntries == 1 && entryError != null) { |
| status = entryError.getStatus(); |
| } else { |
| status = new Status(IStatus.WARNING, CUIPlugin.PLUGIN_ID, -1, |
| NLS.bind(CPathEntryMessages.CPElement_status_multiplePathErrors, String.valueOf(nErrorEntries)), |
| null); |
| } |
| } |
| fContext.statusChanged(status); |
| } |
| |
| private void updateStatus(List<?> selected) { |
| if (selected.size() != 1) { |
| updateStatus(); |
| return; |
| } |
| CPElement element = null; |
| if (selected.get(0) instanceof CPElement) { |
| element = (CPElement) selected.get(0); |
| } else if (selected.get(0) instanceof CPElementAttribute) { |
| element = ((CPElementAttribute) selected.get(0)).getParent(); |
| } |
| if (element != null && element.getStatus().getSeverity() != IStatus.OK) { |
| fContext.statusChanged(element.getStatus()); |
| } else { |
| updateStatus(); |
| return; |
| } |
| } |
| |
| private List<CPElementGroup> createGroups(ICElement element, List<?> cPaths) { |
| // create resource groups |
| List<CPElementGroup> resourceGroups = new ArrayList<>(5); |
| fTopGroup = new CPElementGroup(element.getResource()); |
| resourceGroups.add(fTopGroup); |
| // add containers first so that they appear at top of list |
| for (int i = 0; i < cPaths.size(); i++) { |
| CPElement cpelement = (CPElement) cPaths.get(i); |
| switch (cpelement.getEntryKind()) { |
| case IPathEntry.CDT_CONTAINER: |
| fTopGroup.addChild(cpelement); |
| break; |
| } |
| } |
| for (int i = 0; i < cPaths.size(); i++) { |
| CPElement cpelement = (CPElement) cPaths.get(i); |
| switch (cpelement.getEntryKind()) { |
| case IPathEntry.CDT_INCLUDE: |
| case IPathEntry.CDT_MACRO: |
| CPElementGroup resGroup = new CPElementGroup(cpelement.getResource()); |
| int ndx = resourceGroups.indexOf(resGroup); |
| if (ndx == -1) { |
| resourceGroups.add(resGroup); |
| } else { |
| resGroup = resourceGroups.get(ndx); |
| } |
| resGroup.addChild(cpelement); |
| } |
| } |
| |
| // place each path in its appropriate inherited group (or not if |
| // excluded) |
| for (int i = 0; i < cPaths.size(); i++) { |
| CPElement cpelement = (CPElement) cPaths.get(i); |
| switch (cpelement.getEntryKind()) { |
| case IPathEntry.CDT_INCLUDE: |
| case IPathEntry.CDT_MACRO: |
| addPathToResourceGroups(cpelement, null, resourceGroups); |
| } |
| } |
| return resourceGroups; |
| } |
| |
| private void addPathToResourceGroup(CPElement element, CPElementGroup parent, CPElementGroup group) { |
| IPath resPath = element.getPath(); |
| IPath[] exclusions = (IPath[]) element.getAttribute(CPElement.EXCLUSION); |
| if ((group != parent || !group.getResource().equals(element.getResource())) |
| && resPath.isPrefixOf(group.getPath()) |
| && (resPath.equals(group.getPath()) || !CoreModelUtil.isExcludedPath( |
| group.getResource().getFullPath().removeFirstSegments(resPath.segmentCount()), exclusions))) { |
| if (parent != null) { // try to insert at proper place in group... |
| int insertHere = -1; |
| int ndx = parent.indexof(element); |
| if (ndx != -1) { |
| CPElement[] children = parent.getChildren(element.getEntryKind()); |
| for (int i = ndx; i < children.length; i++) { |
| insertHere = group.indexof(new CPElement(children[i], group.getPath(), group.getResource())); |
| if (insertHere != -1) { |
| group.addChild(new CPElement(element, group.getPath(), group.getResource()), insertHere); |
| break; |
| } |
| } |
| } |
| if (insertHere == -1) { |
| group.addChild(new CPElement(element, group.getPath(), group.getResource())); |
| } |
| } else { |
| group.addChild(new CPElement(element, group.getPath(), group.getResource())); |
| } |
| } |
| } |
| |
| private void addPathToResourceGroups(CPElement element, CPElementGroup parent, List<CPElementGroup> groups) { |
| if (parent != null) { |
| parent.addChild(element); |
| } |
| for (int i = 0; i < groups.size(); i++) { |
| CPElementGroup group = groups.get(i); |
| addPathToResourceGroup(element, parent, group); |
| } |
| } |
| |
| private void updatePathOnResourceGroups(CPElement element, List<CPElementGroup> groups) { |
| CPElementGroup parent = element.getParent(); |
| IPath resPath = element.getPath(); |
| IPath[] exclusions = (IPath[]) element.getAttribute(CPElement.EXCLUSION); |
| for (int i = 0; i < groups.size(); i++) { |
| CPElementGroup group = groups.get(i); |
| if (group != parent) { |
| boolean found = false; |
| CPElement[] elements = group.getChildren(element.getEntryKind()); |
| for (CPElement element2 : elements) { |
| if (element2.getInherited() == element) { |
| found = true; |
| if (!CoreModelUtil.isExcludedPath( |
| group.getResource().getFullPath().removeFirstSegments(resPath.segmentCount()), |
| exclusions)) { |
| group.replaceChild(element2, new CPElement(element, group.getPath(), group.getResource())); |
| } else { |
| group.removeChild(element2); |
| } |
| break; |
| } |
| } |
| if (!found) { |
| addPathToResourceGroup(element, parent, group); |
| } |
| } |
| } |
| } |
| |
| private CPElement removePathFromResourceGroups(CPElement element, List<CPElementGroup> groups) { |
| CPElement Inherited = element.getInherited(); |
| CPElementGroup resGroup = element.getParent(); |
| resGroup.removeChild(element); |
| if (Inherited != null) { // applied exclusion to orig. |
| IPath exclude = element.getPath().removeFirstSegments(Inherited.getPath().segmentCount()); |
| IPath[] exclusions = (IPath[]) Inherited.getAttribute(CPElement.EXCLUSION); |
| IPath[] newExlusions = new IPath[exclusions.length + 1]; |
| System.arraycopy(exclusions, 0, newExlusions, 0, exclusions.length); |
| newExlusions[exclusions.length] = exclude; |
| Inherited.setAttribute(CPElement.EXCLUSION, newExlusions); |
| return null; |
| } |
| // remove all inherited |
| for (int i = 0; i < groups.size(); i++) { |
| CPElementGroup group = groups.get(i); |
| CPElement elements[] = group.getChildren(element.getEntryKind()); |
| for (CPElement element2 : elements) { |
| if (element2.getInherited() == element) { |
| group.removeChild(element2); |
| break; |
| } |
| } |
| } |
| return element; |
| } |
| |
| private boolean canAddPath(List<?> selected) { |
| CPElementGroup group = getSelectedGroup(); |
| if (group != null) { |
| return group.getEntryKind() == -1; // resource group |
| } |
| return false; |
| } |
| |
| private boolean canRemove(List<?> selected) { |
| if (selected.size() != 1) { |
| return false; |
| } |
| Object elem = selected.get(0); |
| if (elem instanceof CPElement) { |
| CPElement element = (CPElement) elem; |
| if (element.getParentContainer() == null) { |
| return element.getEntryKind() == IPathEntry.CDT_INCLUDE |
| || element.getEntryKind() == IPathEntry.CDT_MACRO; |
| } |
| } else if (elem instanceof CPElementAttribute) { |
| CPElementAttribute attrib = (CPElementAttribute) elem; |
| if (attrib.getKey().equals(CPElement.EXCLUSION)) { |
| if (((IPath[]) attrib.getValue()).length > 0) { |
| return true; |
| } |
| } |
| } |
| return false; |
| } |
| |
| private void removeEntry() { |
| List<?> selected = getSelection(); |
| Object elem = selected.get(0); |
| if (elem instanceof CPElement) { |
| CPElement element = (CPElement) elem; |
| CPElementGroup parent = element.getParent(); |
| if (removePathFromResourceGroups(element, fIncludeSymPathsList.getElements()) == null) { |
| updatePathOnResourceGroups(element.getInherited(), fIncludeSymPathsList.getElements()); |
| } |
| fIncludeSymPathsList.refresh(); |
| fIncludeSymPathsList.selectElements(new StructuredSelection(parent)); |
| } else if (elem instanceof CPElementAttribute) { |
| CPElementAttribute attrib = (CPElementAttribute) elem; |
| String key = attrib.getKey(); |
| Object value = key.equals(CPElement.EXCLUSION) ? new Path[0] : null; |
| attrib.getParent().setAttribute(key, value); |
| updatePathOnResourceGroups(attrib.getParent(), fIncludeSymPathsList.getElements()); |
| fIncludeSymPathsList.refresh(); |
| } |
| updateStatus(); |
| } |
| |
| private boolean canEdit(List<?> selected) { |
| if (selected.size() != 1) { |
| return false; |
| } |
| Object elem = selected.get(0); |
| if (elem instanceof CPElement) { |
| CPElement element = (CPElement) selected.get(0); |
| if (element.getParentContainer() == null && element.getInherited() == null) { |
| IPath path = (IPath) element.getAttribute(CPElement.BASE_REF); |
| if (path != null && !path.equals(Path.EMPTY)) { |
| return false; |
| } |
| return element.getEntryKind() == IPathEntry.CDT_INCLUDE |
| || element.getEntryKind() == IPathEntry.CDT_MACRO |
| || element.getEntryKind() == IPathEntry.CDT_CONTAINER; |
| } |
| } |
| if (elem instanceof CPElementAttribute) { |
| return true; |
| } |
| return false; |
| } |
| |
| private void editEntry() { |
| List<?> selElements = fIncludeSymPathsList.getSelectedElements(); |
| if (selElements.size() != 1) { |
| return; |
| } |
| Object element = selElements.get(0); |
| |
| if (element instanceof CPElement) { |
| editElementEntry((CPElement) element); |
| } else if (element instanceof CPElementAttribute) { |
| editAttributeEntry((CPElementAttribute) element); |
| } |
| } |
| |
| private void editElementEntry(CPElement element) { |
| IPath path = (IPath) element.getAttribute(CPElement.BASE_REF); |
| if (path != null && !path.equals(Path.EMPTY)) { |
| return; |
| } else if (element.getEntryKind() == IPathEntry.CDT_MACRO) { |
| addSymbol(element); |
| } else if (element.getEntryKind() == IPathEntry.CDT_INCLUDE) { |
| path = (IPath) element.getAttribute(CPElement.BASE); |
| if (path != null && !path.equals(Path.EMPTY)) { |
| CPElement[] includes = openWorkspacePathEntryDialog(null); |
| if (includes != null && includes.length > 0) { |
| includes[0].setExported(element.isExported()); |
| |
| } |
| } else { |
| addInclude(element); |
| } |
| } else if (element.getEntryKind() == IPathEntry.CDT_CONTAINER) { |
| CPElement[] res = null; |
| |
| res = openContainerSelectionDialog(element); |
| if (res != null && res.length > 0) { |
| CPElement curr = res[0]; |
| curr.setExported(element.isExported()); |
| fTopGroup.replaceChild(element, curr); |
| fIncludeSymPathsList.refresh(); |
| } |
| } |
| } |
| |
| private void editAttributeEntry(CPElementAttribute elem) { |
| String key = elem.getKey(); |
| if (key.equals(CPElement.EXCLUSION)) { |
| CPElement selElement = elem.getParent(); |
| ExclusionPatternDialog dialog = new ExclusionPatternDialog(getShell(), selElement); |
| if (dialog.open() == Window.OK) { |
| selElement.setAttribute(CPElement.EXCLUSION, dialog.getExclusionPattern()); |
| updatePathOnResourceGroups(selElement, fIncludeSymPathsList.getElements()); |
| fIncludeSymPathsList.refresh(); |
| updateStatus(); |
| } |
| } |
| } |
| |
| private void exportEntry() { |
| CPElement element = (CPElement) getSelection().get(0); |
| element.setExported(!element.isExported()); // toggle |
| fIncludeSymPathsList.refresh(element); |
| } |
| |
| private boolean canExport(List<?> selected) { |
| if (selected.size() != 1) { |
| return false; |
| } |
| Object elem = selected.get(0); |
| if (elem instanceof CPElement) { |
| CPElement element = (CPElement) selected.get(0); |
| if (element.getParentContainer() == null && element.getInherited() == null) { |
| IPath base_ref = (IPath) element.getAttribute(CPElement.BASE_REF); |
| if (base_ref != null && !base_ref.equals(Path.EMPTY)) |
| return false; |
| return element.getEntryKind() == IPathEntry.CDT_INCLUDE |
| || element.getEntryKind() == IPathEntry.CDT_MACRO; |
| } |
| } |
| return false; |
| } |
| |
| private boolean canMove(List<?> selected) { |
| if (selected.size() == 0) { |
| return false; |
| } |
| for (int i = 0; i < selected.size(); i++) { |
| Object element = selected.get(i); |
| if (!(element instanceof CPElement)) |
| return false; |
| CPElement elem = (CPElement) element; |
| if (elem.getEntryKind() != IPathEntry.CDT_INCLUDE && elem.getEntryKind() != IPathEntry.CDT_MACRO) { |
| return false; |
| } |
| if (elem.getParentContainer() != null || elem.getInherited() != null) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| private boolean canMoveUp(List<?> selected) { |
| if (!canMove(selected)) { |
| return false; |
| } |
| CPElement first = (CPElement) selected.get(0); |
| CPElementGroup parent = first.getParent(); |
| CPElement children[] = parent.getChildren(first.getEntryKind()); |
| int indx = Arrays.asList(children).indexOf(first); |
| if (indx <= 0) { |
| return false; |
| } |
| return true; |
| } |
| |
| private boolean canMoveDown(List<?> selected) { |
| if (!canMove(selected)) { |
| return false; |
| } |
| CPElement last = (CPElement) selected.get(selected.size() - 1); |
| CPElementGroup parent = last.getParent(); |
| CPElement children[] = parent.getChildren(last.getEntryKind()); |
| int indx = Arrays.asList(children).indexOf(last); |
| if (indx >= children.length - 1 || children[indx + 1].getInherited() != null) { |
| return false; |
| } |
| return true; |
| } |
| |
| private boolean moveUp(CPElement element) { |
| boolean rc = false; |
| int kind = element.getEntryKind(); |
| for (CPElementGroup group : fIncludeSymPathsList.getElements()) { |
| CPElement[] children = group.getChildren(kind); |
| for (int k = 0; k < children.length; ++k) { |
| CPElement child = children[k]; |
| if (element.equals(child) || (child.getInherited() != null && child.getInherited().equals(element))) { |
| if (child.getInherited() != null && k > 0 && children[k - 1].getInherited() == null) { |
| break; |
| } |
| int prevIndex = k - 1; |
| if (prevIndex >= 0) { |
| // swap the two |
| children[k] = children[prevIndex]; |
| children[prevIndex] = child; |
| rc = true; |
| break; |
| } |
| } |
| } |
| group.setChildren(children); |
| } |
| fIncludeSymPathsList.refresh(); |
| fIncludeSymPathsList.selectElements(new StructuredSelection(element)); |
| fIncludeSymPathsList.setFocus(); |
| return rc; |
| } |
| |
| /** |
| * |
| */ |
| private boolean moveDown(CPElement element) { |
| boolean rc = false; |
| int kind = element.getEntryKind(); |
| for (CPElementGroup group : fIncludeSymPathsList.getElements()) { |
| CPElement[] children = group.getChildren(kind); |
| for (int k = children.length - 1; k >= 0; --k) { |
| CPElement child = children[k]; |
| if (element.equals(child) || (child.getInherited() != null && child.getInherited().equals(element))) { |
| int prevIndex = k + 1; |
| if (prevIndex < children.length) { |
| // swap the two |
| children[k] = children[prevIndex]; |
| children[prevIndex] = child; |
| rc = true; |
| break; |
| } |
| } |
| } |
| group.setChildren(children); |
| } |
| fIncludeSymPathsList.refresh(); |
| fIncludeSymPathsList.selectElements(new StructuredSelection(element)); |
| fIncludeSymPathsList.setFocus(); |
| return rc; |
| } |
| |
| private CPElementGroup getSelectedGroup() { |
| List<?> selected = fIncludeSymPathsList.getSelectedElements(); |
| if (!selected.isEmpty()) { |
| Object item = selected.get(0); |
| if (item instanceof CPElement) { |
| item = ((CPElement) item).getParent(); |
| } |
| if (item instanceof CPElementGroup) { |
| return (CPElementGroup) item; |
| } |
| } |
| return fTopGroup; |
| } |
| |
| protected void listPageDialogFieldChanged(DialogField field) { |
| if (field == fShowInheritedPaths) { |
| boolean showInherited = fShowInheritedPaths.isSelected(); |
| if (fFilter != null) { |
| fIncludeSymPathsList.getTreeViewer().removeFilter(fFilter); |
| } |
| fFilter = new CPElementFilter( |
| new int[] { -1, IPathEntry.CDT_INCLUDE, IPathEntry.CDT_MACRO, IPathEntry.CDT_CONTAINER }, false, |
| showInherited); |
| fIncludeSymPathsList.getTreeViewer().addFilter(fFilter); |
| fIncludeSymPathsList.refresh(); |
| } |
| updateStatus(); |
| } |
| |
| protected void listPageSelectionChanged(TreeListDialogField<?> field) { |
| List<?> selected = field.getSelectedElements(); |
| field.enableButton(IDX_REMOVE, canRemove(selected)); |
| field.enableButton(IDX_EDIT, canEdit(selected)); |
| field.enableButton(IDX_ADD_CONTRIBUTED, canAddPath(selected)); |
| field.enableButton(IDX_ADD_EXT_INCLUDE, canAddPath(selected)); |
| field.enableButton(IDX_ADD_WS_INCLUDE, canAddPath(selected)); |
| field.enableButton(IDX_ADD_SYMBOL, canAddPath(selected)); |
| field.enableButton(IDX_EXPORT, canExport(selected)); |
| field.enableButton(IDX_DOWN, canMoveDown(selected)); |
| field.enableButton(IDX_UP, canMoveUp(selected)); |
| updateStatus(selected); |
| } |
| |
| protected void ListCustomButtonPressed(TreeListDialogField<?> field, int index) { |
| switch (index) { |
| case IDX_ADD_FOLDER_FILE: |
| addNewPathResource(); |
| break; |
| case IDX_ADD_SYMBOL: |
| addSymbol(null); |
| break; |
| case IDX_ADD_EXT_INCLUDE: |
| addInclude(null); |
| break; |
| case IDX_ADD_WS_INCLUDE: |
| addFromWorkspace(); |
| break; |
| case IDX_ADD_CONTRIBUTED: |
| addContributed(); |
| break; |
| case IDX_EDIT: |
| if (canEdit(field.getSelectedElements())) { |
| editEntry(); |
| } |
| break; |
| case IDX_REMOVE: |
| if (canRemove(field.getSelectedElements())) { |
| removeEntry(); |
| } |
| break; |
| case IDX_DOWN: |
| if (canMoveDown(field.getSelectedElements())) { |
| moveDown((CPElement) field.getSelectedElements().get(0)); |
| } |
| break; |
| case IDX_UP: |
| if (canMoveUp(field.getSelectedElements())) { |
| moveUp((CPElement) field.getSelectedElements().get(0)); |
| } |
| break; |
| case IDX_EXPORT: |
| if (canExport(field.getSelectedElements())) { |
| exportEntry(); |
| } |
| |
| } |
| } |
| |
| protected void ListPageDoubleClicked(TreeListDialogField<?> field) { |
| if (canEdit(fIncludeSymPathsList.getSelectedElements())) { |
| editEntry(); |
| } |
| } |
| |
| protected void ListPageKeyPressed(TreeListDialogField<?> field, KeyEvent event) { |
| if (field == fIncludeSymPathsList) { |
| if (event.character == SWT.DEL && event.stateMask == 0) { |
| List<?> selection = field.getSelectedElements(); |
| if (canEdit(selection)) { |
| removeEntry(); |
| } |
| } |
| } |
| } |
| |
| protected IPathEntry[] getRawPathEntries() { |
| List<CPElement> paths = getCPaths(); |
| IPathEntry[] currEntries = new IPathEntry[paths.size()]; |
| for (int i = 0; i < currEntries.length; i++) { |
| CPElement curr = paths.get(i); |
| currEntries[i] = curr.getPathEntry(); |
| } |
| return currEntries; |
| } |
| |
| protected void addNewPathResource() { |
| Class<?>[] acceptedClasses = new Class[] { ICProject.class, ICContainer.class, ITranslationUnit.class }; |
| TypedElementSelectionValidator validator = new TypedElementSelectionValidator(acceptedClasses, false); |
| ViewerFilter filter = new TypedViewerFilter(acceptedClasses); |
| |
| String title = CPathEntryMessages.IncludeSymbolEntryPage_newResource_title; |
| String message = CPathEntryMessages.IncludeSymbolEntryPage_newResource_description; |
| |
| ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(getShell(), new WorkbenchLabelProvider(), |
| new CElementContentProvider()); |
| dialog.setValidator(validator); |
| dialog.setTitle(title); |
| dialog.setMessage(message); |
| dialog.addFilter(filter); |
| dialog.setInput(fCurrCProject); |
| dialog.setInitialSelection(fCurrCProject); |
| |
| if (dialog.open() == Window.OK) { |
| Object[] elements = dialog.getResult(); |
| IResource resource; |
| if (elements[0] instanceof IResource) { |
| resource = (IResource) elements[0]; |
| } else { |
| resource = ((ICElement) elements[0]).getResource(); |
| } |
| CPElementGroup newGroup = new CPElementGroup(resource); |
| if (!fIncludeSymPathsList.getElements().contains(newGroup)) { |
| List<CPElementGroup> groups = fIncludeSymPathsList.getElements(); |
| for (int i = 0; i < groups.size(); i++) { |
| CPElementGroup group = groups.get(i); |
| if (group.getPath().isPrefixOf(newGroup.getPath())) { |
| CPElement[] cpelements = group.getChildren(); |
| for (CPElement cpelement : cpelements) { |
| if (cpelement.getInherited() == null) { |
| switch (cpelement.getEntryKind()) { |
| case IPathEntry.CDT_INCLUDE: |
| case IPathEntry.CDT_MACRO: |
| addPathToResourceGroup(cpelement, null, newGroup); |
| } |
| } |
| } |
| } |
| } |
| fIncludeSymPathsList.addElement(newGroup); |
| } |
| fIncludeSymPathsList.selectElements(new StructuredSelection(newGroup)); |
| fIncludeSymPathsList.expandElement(newGroup, 1); |
| } |
| } |
| |
| protected void addSymbol(CPElement existing) { |
| // Popup an entry dialog |
| InputDialog dialog; |
| if (existing == null) { |
| dialog = new InputDialog(getShell(), CPathEntryMessages.IncludeSymbolEntryPage_addSymbol_title, |
| CPathEntryMessages.IncludeSymbolEntryPage_addSymbol_message, "", //$NON-NLS-1$ |
| null); |
| } else { |
| StringBuilder initialValue = new StringBuilder(); |
| initialValue.append((String) existing.getAttribute(CPElement.MACRO_NAME)); |
| initialValue.append('='); |
| initialValue.append((String) existing.getAttribute(CPElement.MACRO_VALUE)); |
| dialog = new InputDialog(getShell(), CPathEntryMessages.IncludeSymbolEntryPage_editSymbol_title, |
| CPathEntryMessages.IncludeSymbolEntryPage_editSymbol_message, initialValue.toString(), null); |
| } |
| |
| String symbol = null; |
| if (dialog.open() == Window.OK) { |
| symbol = dialog.getValue(); |
| if (symbol != null && symbol.length() > 0) { |
| CPElementGroup group = getSelectedGroup(); |
| CPElement newPath = new CPElement(fCurrCProject, IPathEntry.CDT_MACRO, |
| group.getResource().getFullPath(), group.getResource()); |
| String name, value = ""; //$NON-NLS-1$ |
| int index = symbol.indexOf("="); //$NON-NLS-1$ |
| if (index != -1) { |
| name = symbol.substring(0, index).trim(); |
| value = symbol.substring(index + 1).trim(); |
| } else { |
| name = symbol.trim(); |
| } |
| if (existing != null) { |
| existing.setAttribute(CPElement.MACRO_NAME, name); |
| existing.setAttribute(CPElement.MACRO_VALUE, value); |
| updatePathOnResourceGroups(existing, fIncludeSymPathsList.getElements()); |
| fIncludeSymPathsList.refresh(); |
| } else { |
| newPath.setAttribute(CPElement.MACRO_NAME, name); |
| newPath.setAttribute(CPElement.MACRO_VALUE, value); |
| if (!group.contains(newPath)) { |
| addPathToResourceGroups(newPath, group, fIncludeSymPathsList.getElements()); |
| fIncludeSymPathsList.refresh(); |
| fIncludeSymPathsList.selectElements(new StructuredSelection(newPath)); |
| } |
| updateStatus(); |
| } |
| } |
| } |
| } |
| |
| protected void addInclude(CPElement existing) { |
| InputDialog dialog; |
| if (existing == null) { |
| dialog = new SelectPathInputDialog(getShell(), CPathEntryMessages.IncludeSymbolEntryPage_addExternal_title, |
| CPathEntryMessages.IncludeSymbolEntryPage_addExternal_message, null, null); |
| } else { |
| dialog = new SelectPathInputDialog(getShell(), CPathEntryMessages.IncludeSymbolEntryPage_editExternal_title, |
| CPathEntryMessages.IncludeSymbolEntryPage_editExternal_message, |
| ((IPath) existing.getAttribute(CPElement.INCLUDE)).toOSString(), null); |
| } |
| String newItem = null; |
| if (dialog.open() == Window.OK) { |
| newItem = dialog.getValue(); |
| if (newItem != null && !newItem.isEmpty()) { |
| if (existing == null) { |
| CPElementGroup group = getSelectedGroup(); |
| CPElement newPath = new CPElement(fCurrCProject, IPathEntry.CDT_INCLUDE, |
| group.getResource().getFullPath(), group.getResource()); |
| newPath.setAttribute(CPElement.INCLUDE, new Path(newItem)); |
| if (!group.contains(newPath)) { |
| addPathToResourceGroups(newPath, group, fIncludeSymPathsList.getElements()); |
| fIncludeSymPathsList.refresh(); |
| fIncludeSymPathsList.selectElements(new StructuredSelection(newPath)); |
| } |
| } else { |
| existing.setAttribute(CPElement.INCLUDE, new Path(newItem)); |
| updatePathOnResourceGroups(existing, fIncludeSymPathsList.getElements()); |
| fIncludeSymPathsList.refresh(); |
| } |
| updateStatus(); |
| } |
| } |
| } |
| |
| protected void addFromWorkspace() { |
| CPElement[] includes = openWorkspacePathEntryDialog(null); |
| if (includes != null && includes.length > 0) { |
| int nElementsChosen = includes.length; |
| CPElementGroup group = getSelectedGroup(); |
| for (int i = 0; i < nElementsChosen; i++) { |
| CPElement curr = includes[i]; |
| if (!group.contains(curr)) { |
| addPathToResourceGroups(curr, group, fIncludeSymPathsList.getElements()); |
| fIncludeSymPathsList.refresh(); |
| fIncludeSymPathsList.selectElements(new StructuredSelection(curr)); |
| updateStatus(); |
| } |
| } |
| } |
| |
| } |
| |
| protected void addContributed() { |
| CPElement[] includes = openContainerSelectionDialog(null); |
| if (includes != null && includes.length > 0) { |
| int nElementsChosen = includes.length; |
| // remove duplicates |
| CPElementGroup group = getSelectedGroup(); |
| for (int i = 0; i < nElementsChosen; i++) { |
| CPElement curr = includes[i]; |
| if (!group.contains(curr)) { |
| addPathToResourceGroups(curr, getSelectedGroup(), fIncludeSymPathsList.getElements()); |
| fIncludeSymPathsList.refresh(); |
| fIncludeSymPathsList.selectElements(new StructuredSelection(curr)); |
| updateStatus(); |
| } |
| } |
| } |
| } |
| |
| protected CPElement[] openWorkspacePathEntryDialog(CPElement existing) { |
| Class<?>[] acceptedClasses = new Class[] { ICProject.class, IProject.class, IContainer.class, |
| ICContainer.class }; |
| TypedElementSelectionValidator validator = new TypedElementSelectionValidator(acceptedClasses, |
| existing == null); |
| ViewerFilter filter = new TypedViewerFilter(acceptedClasses); |
| |
| String title = (existing == null) ? CPathEntryMessages.IncludeSymbolEntryPage_fromWorkspaceDialog_new_title |
| : CPathEntryMessages.IncludeSymbolEntryPage_fromWorkspaceDialog_edit_title; |
| String message = (existing == null) |
| ? CPathEntryMessages.IncludeSymbolEntryPage_fromWorkspaceDialog_new_description |
| : CPathEntryMessages.IncludeSymbolEntryPage_fromWorkspaceDialog_edit_description; |
| |
| ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(getShell(), new WorkbenchLabelProvider(), |
| new CElementContentProvider()); |
| dialog.setValidator(validator); |
| dialog.setTitle(title); |
| dialog.setMessage(message); |
| dialog.addFilter(filter); |
| dialog.setInput(CoreModel.getDefault().getCModel()); |
| if (existing == null) { |
| dialog.setInitialSelection(fCurrCProject); |
| } else { |
| dialog.setInitialSelection(existing.getCProject()); |
| } |
| |
| if (dialog.open() == Window.OK) { |
| Object[] elements = dialog.getResult(); |
| CPElement[] res = new CPElement[elements.length]; |
| for (int i = 0; i < res.length; i++) { |
| IProject project; |
| IPath includePath; |
| if (elements[i] instanceof IResource) { |
| project = ((IResource) elements[i]).getProject(); |
| includePath = ((IResource) elements[i]).getProjectRelativePath(); |
| } else { |
| project = ((ICElement) elements[i]).getCProject().getProject(); |
| includePath = ((ICElement) elements[i]).getResource().getProjectRelativePath(); |
| } |
| CPElementGroup group = getSelectedGroup(); |
| res[i] = new CPElement(fCurrCProject, IPathEntry.CDT_INCLUDE, group.getResource().getFullPath(), |
| group.getResource()); |
| res[i].setAttribute(CPElement.BASE, project.getFullPath().makeRelative()); |
| res[i].setAttribute(CPElement.INCLUDE, includePath); |
| } |
| return res; |
| } |
| return null; |
| } |
| |
| protected CPElement[] openContainerSelectionDialog(CPElement existing) { |
| IContainerEntry elem = null; |
| String title; |
| if (existing == null) { |
| title = CPathEntryMessages.IncludeSymbolEntryPage_ContainerDialog_new_title; |
| } else { |
| title = CPathEntryMessages.IncludeSymbolEntryPage_ContainerDialog_edit_title; |
| elem = (IContainerEntry) existing.getPathEntry(); |
| } |
| CPathContainerWizard wizard = new CPathContainerWizard(elem, null, fCurrCProject, getRawPathEntries(), |
| new int[] { IPathEntry.CDT_INCLUDE, IPathEntry.CDT_MACRO }); |
| wizard.setWindowTitle(title); |
| if (CPathContainerWizard.openWizard(getShell(), wizard) == Window.OK) { |
| IPathEntry parent = wizard.getEntriesParent(); |
| IPathEntry[] elements = wizard.getEntries(); |
| |
| if (elements != null) { |
| CPElement[] res = new CPElement[elements.length]; |
| CPElementGroup group = getSelectedGroup(); |
| for (int i = 0; i < res.length; i++) { |
| if (elements[i].getEntryKind() == IPathEntry.CDT_INCLUDE) { |
| res[i] = new CPElement(fCurrCProject, IPathEntry.CDT_INCLUDE, group.getResource().getFullPath(), |
| group.getResource()); |
| res[i].setAttribute(CPElement.INCLUDE, ((IIncludeEntry) elements[i]).getIncludePath()); |
| res[i].setAttribute(CPElement.BASE_REF, parent.getPath()); |
| } else if (elements[i].getEntryKind() == IPathEntry.CDT_MACRO) { |
| res[i] = new CPElement(fCurrCProject, IPathEntry.CDT_MACRO, group.getResource().getFullPath(), |
| group.getResource()); |
| res[i].setAttribute(CPElement.MACRO_NAME, ((IMacroEntry) elements[i]).getMacroName()); |
| res[i].setAttribute(CPElement.BASE_REF, parent.getPath()); |
| } |
| } |
| return res; |
| } |
| return new CPElement[] { CPElement.createFromExisting(parent, fCurrCProject) }; |
| } |
| return null; |
| } |
| |
| private class SelectPathInputDialog extends InputDialog { |
| |
| public SelectPathInputDialog(Shell parentShell, String dialogTitle, String dialogMessage, String initialValue, |
| IInputValidator validator) { |
| super(parentShell, dialogTitle, dialogMessage, initialValue, validator); |
| } |
| |
| @Override |
| protected void createButtonsForButtonBar(Composite parent) { |
| super.createButtonsForButtonBar(parent); |
| Button browse = createButton(parent, 3, CPathEntryMessages.IncludeSymbolEntryPage_addExternal_button_browse, |
| false); |
| browse.addSelectionListener(new SelectionAdapter() { |
| |
| @Override |
| public void widgetSelected(SelectionEvent ev) { |
| DirectoryDialog dialog = new DirectoryDialog(getShell(), SWT.OPEN); |
| dialog.setText(CPathEntryMessages.IncludeSymbolEntryPage_browseForFolder); |
| String currentName = getText().getText(); |
| if (currentName != null && currentName.trim().length() != 0) { |
| dialog.setFilterPath(currentName); |
| } |
| String dirname = dialog.open(); |
| if (dirname != null) { |
| getText().setText(dirname); |
| } |
| } |
| }); |
| } |
| |
| } |
| |
| @Override |
| public List<?> getSelection() { |
| return fIncludeSymPathsList.getSelectedElements(); |
| } |
| |
| @Override |
| public void setSelection(List<?> selElements) { |
| fIncludeSymPathsList.selectElements(new StructuredSelection(selElements)); |
| } |
| |
| @Override |
| public boolean isEntryKind(int kind) { |
| return kind == IPathEntry.CDT_INCLUDE || kind == IPathEntry.CDT_MACRO; |
| } |
| |
| @Override |
| public void performApply(IProgressMonitor monitor) throws CoreException { |
| } |
| |
| @Override |
| public void performDefaults() { |
| } |
| |
| @Override |
| public List<CPElement> getCPaths() { |
| List<CPElement> cPaths = new ArrayList<>(); |
| List<CPElementGroup> groups = fIncludeSymPathsList.getElements(); |
| for (int i = 0; i < groups.size(); i++) { |
| CPElementGroup group = groups.get(i); |
| CPElement[] elements = group.getChildren(); |
| for (CPElement element : elements) { |
| if (element.getInherited() == null) { |
| cPaths.add(element); |
| } |
| } |
| } |
| return cPaths; |
| } |
| } |