/******************************************************************************* * Copyright (c) 2000, 2012 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 * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package com.redhat.ceylon.eclipse.code.preferences; import static com.redhat.ceylon.eclipse.ui.CeylonResources.CEYLON_NEW_FOLDER; 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.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.internal.corext.buildpath.ClasspathModifier; import org.eclipse.jdt.internal.ui.JavaPlugin; import org.eclipse.jdt.internal.ui.wizards.NewWizardMessages; import org.eclipse.jdt.internal.ui.wizards.buildpaths.BuildPathBasePage; import org.eclipse.jdt.internal.ui.wizards.buildpaths.BuildPathWizard; import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListElement; import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListElementAttribute; import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListElementSorter; import org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField; import org.eclipse.jdt.internal.ui.wizards.dialogfields.IDialogFieldListener; import org.eclipse.jdt.internal.ui.wizards.dialogfields.ITreeListAdapter; import org.eclipse.jdt.internal.ui.wizards.dialogfields.LayoutUtil; import org.eclipse.jdt.internal.ui.wizards.dialogfields.ListDialogField; import org.eclipse.jdt.internal.ui.wizards.dialogfields.StringDialogField; import org.eclipse.jdt.internal.ui.wizards.dialogfields.TreeListDialogField; import org.eclipse.jdt.ui.actions.AbstractOpenWizardAction; import org.eclipse.jface.action.IAction; import org.eclipse.jface.layout.PixelConverter; import org.eclipse.jface.resource.ImageDescriptor; 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; import com.redhat.ceylon.eclipse.code.wizard.AddResourceFolderWizard; import com.redhat.ceylon.eclipse.code.wizard.CreateMultipleResourceFoldersDialog; import com.redhat.ceylon.eclipse.ui.CeylonPlugin; public class ResourceContainerWorkbookPage extends BuildPathBasePage { // private static final String IGNORE_OPTIONAL_PROBLEMS = "ignore_optional_problems"; private static final ImageDescriptor NEW_FOLDER_ICON = CeylonPlugin.imageRegistry() .getDescriptor(CEYLON_NEW_FOLDER); private class OpenBuildPathWizardAction extends AbstractOpenWizardAction implements IPropertyChangeListener { private final BuildPathWizard fWizard; private final List<Object> fSelectedElements; public OpenBuildPathWizardAction(BuildPathWizard wizard) { fWizard= wizard; addPropertyChangeListener(this); fSelectedElements= fFoldersList.getSelectedElements(); } /** * {@inheritDoc} */ @Override protected INewWizard createWizard() throws CoreException { return fWizard; } /** * {@inheritDoc} * @since 3.7 */ @Override protected Shell getShell() { return ResourceContainerWorkbookPage.this.getShell(); } /** * {@inheritDoc} */ 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<CPListElement> insertedElements= fWizard.getInsertedElements(); refresh(insertedElements, fWizard.getRemovedElements(), fWizard.getModifiedElements(), fWizard.getOutputLocation()); if (insertedElements.isEmpty()) { fFoldersList.postSetSelection(new StructuredSelection(fSelectedElements)); } } } private static AddResourceFolderWizard newResourceFolderWizard(CPListElement element, List<CPListElement> existingElements, String outputLocation, boolean newFolder) { CPListElement[] existing= existingElements.toArray(new CPListElement[existingElements.size()]); AddResourceFolderWizard wizard= new AddResourceFolderWizard(existing, element, new Path(outputLocation).makeAbsolute(), false, newFolder, newFolder, newFolder?CPListElement.isProjectSourceFolder(existing, element.getJavaProject()):false, newFolder, "Resource", NEW_FOLDER_ICON); wizard.setDoFlushChange(false); return wizard; } private static AddResourceFolderWizard newLinkedResourceFolderWizard(CPListElement element, List<CPListElement> existingElements, String outputLocation, boolean newFolder) { CPListElement[] existing= existingElements.toArray(new CPListElement[existingElements.size()]); AddResourceFolderWizard wizard= new AddResourceFolderWizard(existing, element, new Path(outputLocation).makeAbsolute(), true, newFolder, newFolder, newFolder?CPListElement.isProjectSourceFolder(existing, element.getJavaProject()):false, newFolder, "Resource", NEW_FOLDER_ICON); wizard.setDoFlushChange(false); return wizard; } // private static EditFilterWizard newEditFilterWizard(CPListElement element, // List<CPListElement> existingElements, String outputLocation) { // CPListElement[] existing= existingElements.toArray(new CPListElement[existingElements.size()]); // EditFilterWizard result = new EditFilterWizard(existing, element, new Path(outputLocation).makeAbsolute()); // result.setDoFlushChange(false); // return result; // } private final ListDialogField<CPListElement> fClassPathList; private IJavaProject fCurrJProject; private Control fSWTControl; private final TreeListDialogField<CPListElement> fFoldersList; private final StringDialogField fJavaOutputLocationField; // private final SelectionButtonDialogField fUseFolderOutputs; private final int IDX_ADD= 0; private final int IDX_ADD_LINK= 1; private final int IDX_EDIT= 3; // private final int IDX_TOGGLE= 4; private final int IDX_REMOVE= 4; public ResourceContainerWorkbookPage(ListDialogField<CPListElement> classPathList, StringDialogField javaOutputLocationField) { fClassPathList= classPathList; fJavaOutputLocationField= javaOutputLocationField; fSWTControl= null; SourceContainerAdapter adapter= new SourceContainerAdapter(); String[] buttonLabels; buttonLabels= new String[] { NewWizardMessages.SourceContainerWorkbookPage_folders_add_button, "L&ink Folder...", null, NewWizardMessages.SourceContainerWorkbookPage_folders_edit_button, // "Toggl&e", NewWizardMessages.SourceContainerWorkbookPage_folders_remove_button }; fFoldersList= new TreeListDialogField<CPListElement>(adapter, buttonLabels, new ResourceListLabelProvider()); fFoldersList.setDialogFieldListener(adapter); fFoldersList.setLabelText("Resource folders on build pat&h:"); fFoldersList.setViewerComparator(new CPListElementSorter()); fFoldersList.enableButton(IDX_EDIT, false); // fFoldersList.enableButton(IDX_TOGGLE, false); fFoldersList.enableButton(IDX_REMOVE, false); // fUseFolderOutputs= new SelectionButtonDialogField(SWT.CHECK); // fUseFolderOutputs.setSelection(false); // fUseFolderOutputs.setLabelText(NewWizardMessages.SourceContainerWorkbookPage_folders_check); // fUseFolderOutputs.setDialogFieldListener(adapter); } @Override public void init(IJavaProject jproject) { fCurrJProject= jproject; if (Display.getCurrent() != null) { updateFoldersList(); } else { Display.getDefault().asyncExec(new Runnable() { public void run() { updateFoldersList(); } }); } } private void updateFoldersList() { if (fSWTControl == null || fSWTControl.isDisposed()) { return; } ArrayList<CPListElement> folders= new ArrayList<CPListElement>(); // boolean useFolderOutputs= false; List<CPListElement> cpelements= fClassPathList.getElements(); for (int i= 0; i < cpelements.size(); i++) { CPListElement cpe= cpelements.get(i); if (cpe.getEntryKind() == IClasspathEntry.CPE_SOURCE) { folders.add(cpe); // boolean hasOutputFolder= cpe.getAttribute(CPListElement.OUTPUT)!=null; // if (hasOutputFolder) { // useFolderOutputs= true; // } } } fFoldersList.setElements(folders); // fUseFolderOutputs.setSelection(useFolderOutputs); // for (int i= 0; i < folders.size(); i++) { // CPListElement cpe= folders.get(i); // IPath[] ePatterns= (IPath[]) cpe.getAttribute(CPListElement.EXCLUSION); // IPath[] iPatterns= (IPath[])cpe.getAttribute(CPListElement.INCLUSION); // boolean hasOutputFolder= cpe.getAttribute(CPListElement.OUTPUT)!=null; // if (ePatterns.length > 0 || iPatterns.length > 0 || hasOutputFolder) { // fFoldersList.expandElement(cpe, 3); // } // } } @Override public Control getControl(Composite parent) { PixelConverter converter= new PixelConverter(parent); Composite composite= new Composite(parent, SWT.NONE); LayoutUtil.doDefaultLayout(composite, new DialogField[] { fFoldersList, fJavaOutputLocationField }, true, SWT.DEFAULT, SWT.DEFAULT); LayoutUtil.setHorizontalGrabbing(fFoldersList.getTreeControl(null)); int buttonBarWidth= converter.convertWidthInCharsToPixels(24); fFoldersList.setButtonsMinWidth(buttonBarWidth); fSWTControl= composite; // expand // List<CPListElement> elements= fFoldersList.getElements(); // for (int i= 0; i < elements.size(); i++) { // CPListElement elem= elements.get(i); // IPath[] exclusionPatterns= (IPath[]) elem.getAttribute(CPListElement.EXCLUSION); // IPath[] inclusionPatterns= (IPath[]) elem.getAttribute(CPListElement.INCLUSION); // IPath output= (IPath) elem.getAttribute(CPListElement.OUTPUT); // if (exclusionPatterns.length > 0 || inclusionPatterns.length > 0 || output != null) { // fFoldersList.expandElement(elem, 3); // } // } return composite; } private Shell getShell() { if (fSWTControl != null) { return fSWTControl.getShell(); } return JavaPlugin.getActiveWorkbenchShell(); } private class SourceContainerAdapter implements ITreeListAdapter<CPListElement>, IDialogFieldListener { private final Object[] EMPTY_ARR= new Object[0]; // -------- IListAdapter -------- public void customButtonPressed(TreeListDialogField<CPListElement> field, int index) { sourcePageCustomButtonPressed(field, index); } public void selectionChanged(TreeListDialogField<CPListElement> field) { sourcePageSelectionChanged(field); } public void doubleClicked(TreeListDialogField<CPListElement> field) { sourcePageDoubleClicked(field); } public void keyPressed(TreeListDialogField<CPListElement> field, KeyEvent event) { sourcePageKeyPressed(field, event); } public Object[] getChildren(TreeListDialogField<CPListElement> field, Object element) { // if (element instanceof CPListElement) { // return ((CPListElement) element).getChildren(true); // } return EMPTY_ARR; } public Object getParent(TreeListDialogField<CPListElement> field, Object element) { if (element instanceof CPListElementAttribute) { return ((CPListElementAttribute) element).getParent(); } return null; } public boolean hasChildren(TreeListDialogField<CPListElement> field, Object element) { return false;//(element instanceof CPListElement); } // ---------- IDialogFieldListener -------- public void dialogFieldChanged(DialogField field) { sourcePageDialogFieldChanged(field); } } protected void sourcePageKeyPressed(TreeListDialogField<CPListElement> field, KeyEvent event) { if (field == fFoldersList) { if (event.character == SWT.DEL && event.stateMask == 0) { List<Object> selection= field.getSelectedElements(); if (canRemove(selection)) { removeEntry(); } } } } protected void sourcePageDoubleClicked(TreeListDialogField<CPListElement> field) { if (field == fFoldersList) { List<Object> selection= field.getSelectedElements(); if (canEdit(selection)) { editEntry(); } } } protected void sourcePageCustomButtonPressed(DialogField field, int index) { if (field == fFoldersList) { if (index == IDX_ADD) { IProject project= fCurrJProject.getProject(); if (project.isAccessible() && hasFolders(project)) { List<CPListElement> existingElements= fFoldersList.getElements(); CPListElement[] existing= existingElements.toArray(new CPListElement[existingElements.size()]); CreateMultipleResourceFoldersDialog dialog= new CreateMultipleResourceFoldersDialog(fCurrJProject, existing, fJavaOutputLocationField.getText(), "Resource", NEW_FOLDER_ICON, getShell()); if (dialog.open() == Window.OK) { refresh(dialog.getInsertedElements(), dialog.getRemovedElements(), dialog.getModifiedElements(), dialog.getOutputLocation()); } } else { CPListElement newElement= new CPListElement(fCurrJProject, IClasspathEntry.CPE_SOURCE); AddResourceFolderWizard wizard= newResourceFolderWizard(newElement, fFoldersList.getElements(), fJavaOutputLocationField.getText(), true); OpenBuildPathWizardAction action= new OpenBuildPathWizardAction(wizard); action.run(); } } else if (index == IDX_ADD_LINK) { CPListElement newElement= new CPListElement(fCurrJProject, IClasspathEntry.CPE_SOURCE); AddResourceFolderWizard wizard= newLinkedResourceFolderWizard(newElement, fFoldersList.getElements(), fJavaOutputLocationField.getText(), true); OpenBuildPathWizardAction action= new OpenBuildPathWizardAction(wizard); action.run(); } else if (index == IDX_EDIT/*||index == IDX_TOGGLE*/) { editEntry(); } else if (index == IDX_REMOVE) { removeEntry(); } } } private boolean hasFolders(IContainer container) { try { IResource[] members= container.members(); for (int i= 0; i < members.length; i++) { if (members[i] instanceof IContainer) { return true; } } } catch (CoreException e) { // ignore } List<CPListElement> elements= fFoldersList.getElements(); if (elements.size() > 1) return true; if (elements.size() == 0) return false; CPListElement single= elements.get(0); if (single.getPath().equals(fCurrJProject.getPath())) return false; return true; } private void editEntry() { List<Object> selElements= fFoldersList.getSelectedElements(); if (selElements.size() != 1) { return; } Object elem= selElements.get(0); if (fFoldersList.getIndexOfElement(elem) != -1) { editElementEntry((CPListElement) elem); } /*else if (elem instanceof CPListElementAttribute) { editAttributeEntry((CPListElementAttribute) elem); }*/ } private void editElementEntry(CPListElement elem) { if (elem.getLinkTarget() != null) { AddResourceFolderWizard wizard= newLinkedResourceFolderWizard(elem, fFoldersList.getElements(), fJavaOutputLocationField.getText(), false); OpenBuildPathWizardAction action= new OpenBuildPathWizardAction(wizard); action.run(); } else { AddResourceFolderWizard wizard= newResourceFolderWizard(elem, fFoldersList.getElements(), fJavaOutputLocationField.getText(), false); OpenBuildPathWizardAction action= new OpenBuildPathWizardAction(wizard); action.run(); } } // private void editAttributeEntry(CPListElementAttribute elem) { // String key= elem.getKey(); // if (key.equals(CPListElement.OUTPUT)) { // CPListElement selElement= elem.getParent(); // OutputLocationDialog dialog= new OutputLocationDialog(getShell(), selElement, // fClassPathList.getElements(), // new Path(fJavaOutputLocationField.getText()).makeAbsolute(), true); // if (dialog.open() == Window.OK) { // selElement.setAttribute(CPListElement.OUTPUT, dialog.getOutputLocation()); // fFoldersList.refresh(); // fClassPathList.dialogFieldChanged(); // validate // } // } else if (key.equals(CPListElement.EXCLUSION) || key.equals(CPListElement.INCLUSION)) { // EditFilterWizard wizard= newEditFilterWizard(elem.getParent(), // fFoldersList.getElements(), fJavaOutputLocationField.getText()); // OpenBuildPathWizardAction action= new OpenBuildPathWizardAction(wizard); // action.run(); // } else if (key.equals(IGNORE_OPTIONAL_PROBLEMS)) { // String newValue= "true".equals(elem.getValue()) ? null : "true"; //$NON-NLS-1$ //$NON-NLS-2$ // elem.setValue(newValue); // fFoldersList.refresh(elem); // } else { // if (editCustomAttribute(getShell(), elem)) { // fFoldersList.refresh(); // fClassPathList.dialogFieldChanged(); // validate // } // } // } /** * @param field the dialog field */ protected void sourcePageSelectionChanged(DialogField field) { List<Object> selected= fFoldersList.getSelectedElements(); // boolean isIgnoreOptionalProblems= selected.size() == 1 // && selected.get(0) instanceof CPListElementAttribute // && IGNORE_OPTIONAL_PROBLEMS.equals(((CPListElementAttribute) selected.get(0)).getKey()); /*fFoldersList.getButton(IDX_EDIT).setText(isIgnoreOptionalProblems ? NewWizardMessages.SourceContainerWorkbookPage_folders_toggle_button : NewWizardMessages.SourceContainerWorkbookPage_folders_edit_button);*/ /*if (isIgnoreOptionalProblems) { fFoldersList.enableButton(IDX_TOGGLE, canEdit(selected)); fFoldersList.enableButton(IDX_EDIT, false); } else { fFoldersList.enableButton(IDX_TOGGLE, false); fFoldersList.enableButton(IDX_EDIT, canEdit(selected)); }*/ fFoldersList.enableButton(IDX_EDIT, canEdit(selected)); fFoldersList.enableButton(IDX_REMOVE, canRemove(selected)); boolean noAttributes= containsOnlyTopLevelEntries(selected); fFoldersList.enableButton(IDX_ADD, noAttributes); } private void removeEntry() { List<Object> selElements= fFoldersList.getSelectedElements(); // for (int i= selElements.size() - 1; i >= 0 ; i--) { // Object elem= selElements.get(i); // if (elem instanceof CPListElementAttribute) { // CPListElementAttribute attrib= (CPListElementAttribute) elem; // String key= attrib.getKey(); // if (attrib.isBuiltIn()) { // Object value= null; // if (key.equals(CPListElement.EXCLUSION) || // key.equals(CPListElement.INCLUSION)) { // value= new Path[0]; // } // attrib.getParent().setAttribute(key, value); // } else { // removeCustomAttribute(attrib); // } // selElements.remove(i); // } // } if (selElements.isEmpty()) { fFoldersList.refresh(); fClassPathList.dialogFieldChanged(); // validate } else { for (Iterator<Object> iter= selElements.iterator(); iter.hasNext();) { CPListElement element= (CPListElement)iter.next(); if (element.getEntryKind() == IClasspathEntry.CPE_SOURCE) { List<CPListElement> list= ClasspathModifier.removeFilters(element.getPath(), fCurrJProject, fFoldersList.getElements()); for (Iterator<CPListElement> iterator= list.iterator(); iterator.hasNext();) { CPListElement modified= iterator.next(); fFoldersList.refresh(modified); fFoldersList.expandElement(modified, 3); } } } fFoldersList.removeElements(selElements); } } private boolean canRemove(List<Object> selElements) { if (selElements.size() == 0) { return false; } for (int i= 0; i < selElements.size(); i++) { Object elem= selElements.get(i); /*if (elem instanceof CPListElementAttribute) { CPListElementAttribute attrib= (CPListElementAttribute) elem; String key= attrib.getKey(); if (attrib.isBuiltIn()) { if (CPListElement.INCLUSION.equals(key)) { if (((IPath[]) attrib.getValue()).length == 0) { return false; } } else if (CPListElement.EXCLUSION.equals(key)) { if (((IPath[]) attrib.getValue()).length == 0) { return false; } } else if (attrib.getValue() == null) { return false; } } else { if (!canRemoveCustomAttribute(attrib)) { return false; } } } else*/ if (elem instanceof CPListElement) { CPListElement curr= (CPListElement) elem; if (curr.getParentContainer() != null) { return false; } } } return true; } private boolean canEdit(List<Object> selElements) { if (selElements.size() != 1) { return false; } Object elem= selElements.get(0); if (elem instanceof CPListElement) { CPListElement cp= ((CPListElement)elem); if (cp.getPath().equals(cp.getJavaProject().getPath())) return false; return true; } // if (elem instanceof CPListElementAttribute) { // CPListElementAttribute attrib= (CPListElementAttribute) elem; // if (attrib.isBuiltIn()) { // return true; // } else if (IGNORE_OPTIONAL_PROBLEMS.equals(attrib.getKey())) { // return true; // } else { // return canEditCustomAttribute(attrib); // } // } return false; } private void sourcePageDialogFieldChanged(DialogField field) { if (fCurrJProject == null) { // not initialized return; } // if (field == fUseFolderOutputs) { // if (!fUseFolderOutputs.isSelected()) { // int nFolders= fFoldersList.getSize(); // for (int i= 0; i < nFolders; i++) { // CPListElement cpe= fFoldersList.getElement(i); // cpe.setAttribute(CPListElement.OUTPUT, null); // } // } // fFoldersList.refresh(); // fFoldersList.dialogFieldChanged(); // validate // } else if (field == fFoldersList) { updateClasspathList(); fClassPathList.dialogFieldChanged(); // validate } } private void updateClasspathList() { List<CPListElement> srcelements= fFoldersList.getElements(); List<CPListElement> cpelements= fClassPathList.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--) { CPListElement cpe= 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()) { fClassPathList.setElements(cpelements); } } @Override public List<Object> 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 == IClasspathEntry.CPE_SOURCE; } private void refresh(List<CPListElement> insertedElements, List<?> removedElements, List<CPListElement> modifiedElements, IPath outputLocation) { fFoldersList.addElements(insertedElements); for (Iterator<CPListElement> iter= insertedElements.iterator(); iter.hasNext();) { CPListElement element= iter.next(); fFoldersList.expandElement(element, 3); } fFoldersList.removeElements(removedElements); for (Iterator<CPListElement> iter= modifiedElements.iterator(); iter.hasNext();) { CPListElement element= 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)); } fJavaOutputLocationField.setText(outputLocation.makeRelative().toOSString()); } /** * {@inheritDoc} */ @Override public void setFocus() { fFoldersList.setFocus(); } }