| /******************************************************************************* |
| * Copyright (c) 2000, 2017 IBM 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 |
| * |
| *******************************************************************************/ |
| package org.eclipse.dltk.internal.ui.wizards.buildpath; |
| |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| 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.Path; |
| import org.eclipse.dltk.core.IBuildpathEntry; |
| import org.eclipse.dltk.core.IScriptProject; |
| import org.eclipse.dltk.internal.core.util.Util; |
| import org.eclipse.dltk.internal.corext.buildpath.BuildpathModifier; |
| import org.eclipse.dltk.internal.ui.wizards.NewWizardMessages; |
| import org.eclipse.dltk.internal.ui.wizards.dialogfields.DialogField; |
| import org.eclipse.dltk.internal.ui.wizards.dialogfields.IDialogFieldListener; |
| import org.eclipse.dltk.internal.ui.wizards.dialogfields.ITreeListAdapter; |
| import org.eclipse.dltk.internal.ui.wizards.dialogfields.LayoutUtil; |
| import org.eclipse.dltk.internal.ui.wizards.dialogfields.ListDialogField; |
| import org.eclipse.dltk.internal.ui.wizards.dialogfields.TreeListDialogField; |
| import org.eclipse.dltk.ui.DLTKUIPlugin; |
| import org.eclipse.dltk.ui.actions.AbstractOpenWizardAction; |
| import org.eclipse.dltk.ui.util.PixelConverter; |
| import org.eclipse.jface.action.IAction; |
| import org.eclipse.jface.util.IPropertyChangeListener; |
| import org.eclipse.jface.util.PropertyChangeEvent; |
| import org.eclipse.jface.viewers.StructuredSelection; |
| import org.eclipse.jface.window.Window; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.KeyEvent; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.ui.INewWizard; |
| |
| public class SourceContainerWorkbookPage extends BuildPathBasePage { |
| |
| public class OpenBuildPathWizardAction extends AbstractOpenWizardAction |
| implements IPropertyChangeListener { |
| |
| private final BuildPathWizard fWizard; |
| private final List fSelectedElements; |
| |
| public OpenBuildPathWizardAction(BuildPathWizard wizard) { |
| setShell(SourceContainerWorkbookPage.this.getShell()); |
| fWizard = wizard; |
| addPropertyChangeListener(this); |
| fSelectedElements = fFoldersList.getSelectedElements(); |
| } |
| |
| @Override |
| protected INewWizard createWizard() throws CoreException { |
| return fWizard; |
| } |
| |
| @Override |
| public void propertyChange(PropertyChangeEvent event) { |
| if (event.getProperty().equals(IAction.RESULT)) { |
| if (event.getNewValue().equals(Boolean.TRUE)) { |
| finishWizard(); |
| } else { |
| fWizard.cancel(); |
| } |
| } |
| } |
| |
| protected void finishWizard() { |
| List insertedElements = fWizard.getInsertedElements(); |
| refresh(insertedElements, fWizard.getRemovedElements(), |
| fWizard.getModifiedElements()); |
| |
| if (insertedElements.isEmpty()) { |
| fFoldersList.postSetSelection( |
| new StructuredSelection(fSelectedElements)); |
| } |
| } |
| |
| } |
| |
| protected static AddSourceFolderWizard newSourceFolderWizard( |
| BPListElement element, List<BPListElement> existingElements, |
| boolean newFolder) { |
| BPListElement[] existing = existingElements |
| .toArray(new BPListElement[existingElements.size()]); |
| AddSourceFolderWizard wizard = new AddSourceFolderWizard(existing, |
| element, false, newFolder, newFolder, |
| newFolder ? BPListElement.isProjectSourceFolder(existing, |
| element.getScriptProject()) : false, |
| newFolder); |
| wizard.setDoFlushChange(false); |
| return wizard; |
| } |
| |
| private static AddSourceFolderWizard newLinkedSourceFolderWizard( |
| BPListElement element, List<BPListElement> existingElements, |
| boolean newFolder) { |
| BPListElement[] existing = existingElements |
| .toArray(new BPListElement[existingElements.size()]); |
| AddSourceFolderWizard wizard = new AddSourceFolderWizard(existing, |
| element, true, newFolder, newFolder, |
| newFolder ? BPListElement.isProjectSourceFolder(existing, |
| element.getScriptProject()) : false, |
| newFolder); |
| wizard.setDoFlushChange(false); |
| return wizard; |
| } |
| |
| private static EditFilterWizard newEditFilterWizard(BPListElement element, |
| List<BPListElement> existingElements) { |
| BPListElement[] existing = existingElements |
| .toArray(new BPListElement[existingElements.size()]); |
| EditFilterWizard result = new EditFilterWizard(existing, element); |
| result.setDoFlushChange(false); |
| return result; |
| } |
| |
| private ListDialogField fBuildpathList; |
| protected IScriptProject fCurrJProject; |
| |
| private Control fSWTControl; |
| protected TreeListDialogField fFoldersList; |
| |
| private final int IDX_ADD = 0; |
| private final int IDX_ADD_LINK = 1; |
| private final int IDX_EDIT = 3; |
| private final int IDX_REMOVE = 4; |
| |
| protected int getIDX_ADD() { |
| return IDX_ADD; |
| } |
| |
| protected int getIDX_ADD_LINK() { |
| return IDX_ADD_LINK; |
| } |
| |
| protected int getIDX_EDIT() { |
| return IDX_EDIT; |
| } |
| |
| protected int getIDX_REMOVE() { |
| return IDX_REMOVE; |
| } |
| |
| public SourceContainerWorkbookPage(ListDialogField buildpathList) { |
| fBuildpathList = buildpathList; |
| fSWTControl = null; |
| } |
| |
| /** |
| * Initialize container elements. This code should not be in the constructor |
| * in order to enable extensibility |
| */ |
| protected void initContainerElements() { |
| SourceContainerAdapter adapter = new SourceContainerAdapter(); |
| |
| String[] buttonLabels; |
| |
| buttonLabels = new String[] { |
| NewWizardMessages.SourceContainerWorkbookPage_folders_add_button, |
| NewWizardMessages.SourceContainerWorkbookPage_folders_link_source_button, |
| /* 1 */null, |
| NewWizardMessages.SourceContainerWorkbookPage_folders_edit_button, |
| NewWizardMessages.SourceContainerWorkbookPage_folders_remove_button }; |
| |
| fFoldersList = new TreeListDialogField(adapter, buttonLabels, |
| new BPListLabelProvider()); |
| fFoldersList.setDialogFieldListener(adapter); |
| fFoldersList.setLabelText( |
| NewWizardMessages.SourceContainerWorkbookPage_folders_label); |
| |
| fFoldersList.setViewerComparator(new BPListElementSorter()); |
| fFoldersList.enableButton(getIDX_EDIT(), false); |
| } |
| |
| @Override |
| public void setTitle(String title) { |
| fFoldersList.setLabelText(title); |
| } |
| |
| @Override |
| public void init(IScriptProject jproject) { |
| fCurrJProject = jproject; |
| if (Display.getCurrent() != null) { |
| updateFoldersList(); |
| } else { |
| Display.getDefault().asyncExec(() -> updateFoldersList()); |
| } |
| } |
| |
| protected void updateFoldersList() { |
| ArrayList<BPListElement> folders = new ArrayList<BPListElement>(); |
| |
| List<?> cpelements = fBuildpathList.getElements(); |
| for (int i = 0; i < cpelements.size(); i++) { |
| BPListElement cpe = (BPListElement) cpelements.get(i); |
| if (cpe.getEntryKind() == IBuildpathEntry.BPE_SOURCE) { |
| folders.add(cpe); |
| } |
| } |
| fFoldersList.setElements(folders); |
| |
| for (int i = 0; i < folders.size(); i++) { |
| BPListElement cpe = folders.get(i); |
| IPath[] ePatterns = (IPath[]) cpe |
| .getAttribute(BPListElement.EXCLUSION); |
| IPath[] iPatterns = (IPath[]) cpe |
| .getAttribute(BPListElement.INCLUSION); |
| if (ePatterns.length > 0 || iPatterns.length > 0) { |
| fFoldersList.expandElement(cpe, 3); |
| } |
| } |
| } |
| |
| @Override |
| public Control getControl(Composite parent) { |
| |
| initContainerElements(); |
| |
| PixelConverter converter = new PixelConverter(parent); |
| Composite composite = new Composite(parent, SWT.NONE); |
| |
| LayoutUtil.doDefaultLayout(composite, |
| new DialogField[] { fFoldersList }, true, SWT.DEFAULT, |
| SWT.DEFAULT); |
| LayoutUtil.setHorizontalGrabbing(fFoldersList.getTreeControl(null)); |
| |
| int buttonBarWidth = converter.convertWidthInCharsToPixels(24); |
| fFoldersList.setButtonsMinWidth(buttonBarWidth); |
| |
| fSWTControl = composite; |
| |
| // expand |
| List elements = fFoldersList.getElements(); |
| for (int i = 0; i < elements.size(); i++) { |
| BPListElement elem = (BPListElement) elements.get(i); |
| IPath[] exclusionPatterns = (IPath[]) elem |
| .getAttribute(BPListElement.EXCLUSION); |
| IPath[] inclusionPatterns = (IPath[]) elem |
| .getAttribute(BPListElement.INCLUSION); |
| if (exclusionPatterns.length > 0 || inclusionPatterns.length > 0) { |
| fFoldersList.expandElement(elem, 3); |
| } |
| } |
| return composite; |
| } |
| |
| protected Shell getShell() { |
| if (fSWTControl != null) { |
| return fSWTControl.getShell(); |
| } |
| return DLTKUIPlugin.getActiveWorkbenchShell(); |
| } |
| |
| public class SourceContainerAdapter |
| implements ITreeListAdapter, IDialogFieldListener { |
| |
| private final Object[] EMPTY_ARR = new Object[0]; |
| |
| // -------- IListAdapter -------- |
| @Override |
| public void customButtonPressed(TreeListDialogField field, int index) { |
| sourcePageCustomButtonPressed(field, index); |
| } |
| |
| @Override |
| public void selectionChanged(TreeListDialogField field) { |
| sourcePageSelectionChanged(field); |
| } |
| |
| @Override |
| public void doubleClicked(TreeListDialogField field) { |
| sourcePageDoubleClicked(field); |
| } |
| |
| @Override |
| public void keyPressed(TreeListDialogField field, KeyEvent event) { |
| sourcePageKeyPressed(field, event); |
| } |
| |
| @Override |
| public Object[] getChildren(TreeListDialogField field, Object element) { |
| if (element instanceof BPListElement) { |
| return ((BPListElement) element).getChildren(); |
| } |
| return EMPTY_ARR; |
| } |
| |
| @Override |
| public Object getParent(TreeListDialogField field, Object element) { |
| if (element instanceof BPListElementAttribute) { |
| return ((BPListElementAttribute) element).getParent(); |
| } |
| return null; |
| } |
| |
| @Override |
| public boolean hasChildren(TreeListDialogField field, Object element) { |
| return (element instanceof BPListElement); |
| } |
| |
| // ---------- IDialogFieldListener -------- |
| @Override |
| public void dialogFieldChanged(DialogField field) { |
| sourcePageDialogFieldChanged(field); |
| } |
| |
| } |
| |
| protected void sourcePageKeyPressed(TreeListDialogField field, |
| KeyEvent event) { |
| if (field == fFoldersList) { |
| if (event.character == SWT.DEL && event.stateMask == 0) { |
| List selection = field.getSelectedElements(); |
| if (canRemove(selection)) { |
| removeEntry(); |
| } |
| } |
| } |
| } |
| |
| protected void sourcePageDoubleClicked(TreeListDialogField field) { |
| if (field == fFoldersList) { |
| List selection = field.getSelectedElements(); |
| if (canEdit(selection)) { |
| editEntry(); |
| } |
| } |
| } |
| |
| protected void sourcePageCustomButtonPressed(DialogField field, int index) { |
| if (field == fFoldersList) { |
| if (index == getIDX_ADD()) { |
| IProject project = fCurrJProject.getProject(); |
| if (project.isAccessible() && hasFolders(project)) { |
| List existingElements = fFoldersList.getElements(); |
| BPListElement[] existing = (BPListElement[]) existingElements |
| .toArray( |
| new BPListElement[existingElements.size()]); |
| CreateMultipleSourceFoldersDialog dialog = new CreateMultipleSourceFoldersDialog( |
| fCurrJProject, existing, getShell()); |
| if (dialog.open() == Window.OK) { |
| refresh(dialog.getInsertedElements(), |
| dialog.getRemovedElements(), |
| dialog.getModifiedElements()); |
| } |
| } else { |
| BPListElement newElement = new BPListElement(fCurrJProject, |
| IBuildpathEntry.BPE_SOURCE, false); |
| AddSourceFolderWizard wizard = newSourceFolderWizard( |
| newElement, fFoldersList.getElements(), true); |
| OpenBuildPathWizardAction action = new OpenBuildPathWizardAction( |
| wizard); |
| action.run(); |
| } |
| } else if (index == getIDX_ADD_LINK()) { |
| BPListElement newElement = new BPListElement(fCurrJProject, |
| IBuildpathEntry.BPE_SOURCE, false); |
| AddSourceFolderWizard wizard = newLinkedSourceFolderWizard( |
| newElement, fFoldersList.getElements(), true); |
| OpenBuildPathWizardAction action = new OpenBuildPathWizardAction( |
| wizard); |
| action.run(); |
| } else if (index == getIDX_EDIT()) { |
| editEntry(); |
| } else if (index == getIDX_REMOVE()) { |
| removeEntry(); |
| } |
| } |
| } |
| |
| protected boolean hasFolders(IContainer container) { |
| |
| try { |
| IResource[] members = container.members(); |
| for (int i = 0; i < members.length; i++) { |
| if (members[i] instanceof IContainer |
| && Util.isValidFolderNameForPackage(container, |
| members[i].getName())) { |
| return true; |
| } |
| } |
| } catch (CoreException e) { |
| // ignore |
| } |
| |
| List elements = fFoldersList.getElements(); |
| if (elements.size() > 1) |
| return true; |
| |
| if (elements.size() == 0) |
| return false; |
| |
| BPListElement single = (BPListElement) elements.get(0); |
| if (single.getPath().equals(fCurrJProject.getPath())) |
| return false; |
| |
| return true; |
| } |
| |
| private void editEntry() { |
| List selElements = fFoldersList.getSelectedElements(); |
| if (selElements.size() != 1) { |
| return; |
| } |
| Object elem = selElements.get(0); |
| if (fFoldersList.getIndexOfElement(elem) != -1) { |
| editElementEntry((BPListElement) elem); |
| } else if (elem instanceof BPListElementAttribute) { |
| editAttributeEntry((BPListElementAttribute) elem); |
| } |
| } |
| |
| private void editElementEntry(BPListElement elem) { |
| if (elem.getLinkTarget() != null) { |
| AddSourceFolderWizard wizard = newLinkedSourceFolderWizard(elem, |
| fFoldersList.getElements(), false); |
| OpenBuildPathWizardAction action = new OpenBuildPathWizardAction( |
| wizard); |
| action.run(); |
| } else { |
| AddSourceFolderWizard wizard = newSourceFolderWizard(elem, |
| fFoldersList.getElements(), false); |
| OpenBuildPathWizardAction action = new OpenBuildPathWizardAction( |
| wizard); |
| action.run(); |
| } |
| } |
| |
| private void editAttributeEntry(BPListElementAttribute elem) { |
| String key = elem.getKey(); |
| if (key.equals(BPListElement.EXCLUSION) |
| || key.equals(BPListElement.INCLUSION)) { |
| EditFilterWizard wizard = newEditFilterWizard(elem.getParent(), |
| fFoldersList.getElements()); |
| OpenBuildPathWizardAction action = new OpenBuildPathWizardAction( |
| wizard); |
| action.run(); |
| fFoldersList.refresh(); |
| fBuildpathList.dialogFieldChanged(); |
| } |
| // else if (key.equals(BPListElement.NATIVE_LIB_PATH)) { |
| // BPListElement selElement= elem.getParent(); |
| // NativeLibrariesDialog dialog= new NativeLibrariesDialog(getShell(), |
| // selElement); |
| // if (dialog.open() == Window.OK) { |
| // selElement.setAttribute(BPListElement.NATIVE_LIB_PATH, |
| // dialog.getNativeLibraryPath()); |
| // fFoldersList.refresh(); |
| // fClassPathList.dialogFieldChanged(); // validate |
| // } |
| // } |
| } |
| |
| protected void sourcePageSelectionChanged(DialogField field) { |
| List selected = fFoldersList.getSelectedElements(); |
| fFoldersList.enableButton(getIDX_EDIT(), canEdit(selected)); |
| fFoldersList.enableButton(getIDX_REMOVE(), canRemove(selected)); |
| boolean noAttributes = containsOnlyTopLevelEntries(selected); |
| fFoldersList.enableButton(getIDX_ADD(), noAttributes); |
| } |
| |
| private void removeEntry() { |
| List selElements = fFoldersList.getSelectedElements(); |
| for (int i = selElements.size() - 1; i >= 0; i--) { |
| Object elem = selElements.get(i); |
| if (elem instanceof BPListElementAttribute) { |
| BPListElementAttribute attrib = (BPListElementAttribute) elem; |
| String key = attrib.getKey(); |
| Object value = null; |
| if (key.equals(BPListElement.EXCLUSION) |
| || key.equals(BPListElement.INCLUSION)) { |
| value = new Path[0]; |
| } |
| attrib.getParent().setAttribute(key, value); |
| selElements.remove(i); |
| } |
| } |
| if (selElements.isEmpty()) { |
| fFoldersList.refresh(); |
| fBuildpathList.dialogFieldChanged(); // validate |
| } else { |
| for (Iterator iter = selElements.iterator(); iter.hasNext();) { |
| BPListElement element = (BPListElement) iter.next(); |
| if (element.getEntryKind() == IBuildpathEntry.BPE_SOURCE) { |
| List list = BuildpathModifier.removeFilters( |
| element.getPath(), fCurrJProject, |
| fFoldersList.getElements()); |
| for (Iterator iterator = list.iterator(); iterator |
| .hasNext();) { |
| BPListElement modified = (BPListElement) iterator |
| .next(); |
| fFoldersList.refresh(modified); |
| fFoldersList.expandElement(modified, 3); |
| } |
| } |
| } |
| fFoldersList.removeElements(selElements); |
| } |
| } |
| |
| private boolean canRemove(List selElements) { |
| if (selElements.size() == 0) { |
| return false; |
| } |
| for (int i = 0; i < selElements.size(); i++) { |
| Object elem = selElements.get(i); |
| if (elem instanceof BPListElementAttribute) { |
| BPListElementAttribute attrib = (BPListElementAttribute) elem; |
| String key = attrib.getKey(); |
| if (BPListElement.INCLUSION.equals(key)) { |
| if (((IPath[]) attrib.getValue()).length == 0) { |
| return false; |
| } |
| } else if (BPListElement.EXCLUSION.equals(key)) { |
| if (((IPath[]) attrib.getValue()).length == 0) { |
| return false; |
| } |
| } else if (attrib.getValue() == null) { |
| return false; |
| } |
| } else if (elem instanceof BPListElement) { |
| BPListElement curr = (BPListElement) elem; |
| if (curr.getParentContainer() != null) { |
| return false; |
| } |
| } |
| } |
| return true; |
| } |
| |
| private boolean canEdit(List selElements) { |
| if (selElements.size() != 1) { |
| return false; |
| } |
| Object elem = selElements.get(0); |
| if (elem instanceof BPListElement) { |
| BPListElement cp = ((BPListElement) elem); |
| if (cp.getPath().equals(cp.getScriptProject().getPath())) |
| return false; |
| |
| return true; |
| } |
| if (elem instanceof BPListElementAttribute) { |
| return true; |
| } |
| return false; |
| } |
| |
| private void sourcePageDialogFieldChanged(DialogField field) { |
| if (fCurrJProject == null) { |
| // not initialized |
| return; |
| } |
| |
| if (field == fFoldersList) { |
| updateBuildpathList(); |
| } |
| } |
| |
| private void updateBuildpathList() { |
| List srcelements = fFoldersList.getElements(); |
| |
| List cpelements = fBuildpathList.getElements(); |
| int nEntries = cpelements.size(); |
| // backwards, as entries will be deleted |
| int lastRemovePos = nEntries; |
| int afterLastSourcePos = 0; |
| for (int i = nEntries - 1; i >= 0; i--) { |
| BPListElement cpe = (BPListElement) cpelements.get(i); |
| int kind = cpe.getEntryKind(); |
| if (isEntryKind(kind)) { |
| if (!srcelements.remove(cpe)) { |
| cpelements.remove(i); |
| lastRemovePos = i; |
| } else if (lastRemovePos == nEntries) { |
| afterLastSourcePos = i + 1; |
| } |
| } |
| } |
| |
| if (!srcelements.isEmpty()) { |
| int insertPos = Math.min(afterLastSourcePos, lastRemovePos); |
| cpelements.addAll(insertPos, srcelements); |
| } |
| |
| if (lastRemovePos != nEntries || !srcelements.isEmpty()) { |
| fBuildpathList.setElements(cpelements); |
| } |
| } |
| |
| @Override |
| public List getSelection() { |
| return fFoldersList.getSelectedElements(); |
| } |
| |
| @Override |
| public void setSelection(List selElements, boolean expand) { |
| fFoldersList.selectElements(new StructuredSelection(selElements)); |
| if (expand) { |
| for (int i = 0; i < selElements.size(); i++) { |
| fFoldersList.expandElement(selElements.get(i), 1); |
| } |
| } |
| } |
| |
| @Override |
| public boolean isEntryKind(int kind) { |
| return kind == IBuildpathEntry.BPE_SOURCE; |
| } |
| |
| protected void refresh(List insertedElements, List removedElements, |
| List modifiedElements) { |
| fFoldersList.addElements(insertedElements); |
| for (Iterator iter = insertedElements.iterator(); iter.hasNext();) { |
| BPListElement element = (BPListElement) iter.next(); |
| fFoldersList.expandElement(element, 3); |
| } |
| |
| fFoldersList.removeElements(removedElements); |
| |
| for (Iterator iter = modifiedElements.iterator(); iter.hasNext();) { |
| BPListElement element = (BPListElement) iter.next(); |
| fFoldersList.refresh(element); |
| fFoldersList.expandElement(element, 3); |
| } |
| |
| fFoldersList.refresh(); // does enforce the order of the entries. |
| if (!insertedElements.isEmpty()) { |
| fFoldersList.postSetSelection( |
| new StructuredSelection(insertedElements)); |
| } |
| } |
| |
| } |