/* * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Eclipse Public License, Version 1.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.eclipse.org/org/documents/epl-v10.php * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.ide.eclipse.adt.internal.wizards.exportgradle; import com.google.common.base.Joiner; import com.google.common.collect.Lists; import com.ibm.icu.text.MessageFormat; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.jdt.core.IJavaModel; import org.eclipse.jdt.core.IJavaModelMarker; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.viewers.CheckStateChangedEvent; import org.eclipse.jface.viewers.CheckboxTableViewer; import org.eclipse.jface.viewers.ICheckStateListener; import org.eclipse.jface.viewers.TableLayout; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Table; import org.eclipse.ui.model.WorkbenchContentProvider; import org.eclipse.ui.model.WorkbenchLabelProvider; import java.util.ArrayList; import java.util.List; /** * Displays a wizard page that lets the user choose the projects for which to create Gradle build * files. *

* Based on {@link org.eclipse.ant.internal.ui.datatransfer.AntBuildfileExportPage} */ public class ProjectSelectionPage extends WizardPage { private final ProjectSetupBuilder mBuilder; private CheckboxTableViewer mTableViewer; private List mSelectedJavaProjects = Lists.newArrayList(); public ProjectSelectionPage(ProjectSetupBuilder builder) { super("GradleExportPage"); //$NON-NLS-1$ mBuilder = builder; setPageComplete(false); setTitle(ExportMessages.PageTitle); setDescription(ExportMessages.PageDescription); } @Override public void createControl(Composite parent) { initializeDialogUnits(parent); Composite workArea = new Composite(parent, SWT.NONE); setControl(workArea); workArea.setLayout(new GridLayout()); workArea.setLayoutData(new GridData(GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL)); Label title = new Label(workArea, SWT.NONE); title.setText(ExportMessages.SelectProjects); Composite listComposite = new Composite(workArea, SWT.NONE); GridLayout layout = new GridLayout(); layout.numColumns = 2; layout.marginWidth = 0; layout.makeColumnsEqualWidth = false; listComposite.setLayout(layout); listComposite.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL | GridData.FILL_BOTH)); Table table = new Table(listComposite, SWT.CHECK | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL); mTableViewer = new CheckboxTableViewer(table); table.setLayout(new TableLayout()); GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); data.heightHint = 300; table.setLayoutData(data); mTableViewer.setContentProvider(new WorkbenchContentProvider() { @Override public Object[] getElements(Object element) { if (element instanceof IJavaProject[]) { return (IJavaProject[]) element; } return null; } }); mTableViewer.setLabelProvider(new WorkbenchLabelProvider()); mTableViewer.addCheckStateListener(new ICheckStateListener() { @Override public void checkStateChanged(CheckStateChangedEvent event) { if (event.getChecked()) { mSelectedJavaProjects.add((IJavaProject) event.getElement()); } else { mSelectedJavaProjects.remove(event.getElement()); } updateEnablement(); } }); initializeProjects(); createSelectionButtons(listComposite); setControl(workArea); updateEnablement(); Dialog.applyDialogFont(parent); } /** * Creates select all/deselect all buttons. */ private void createSelectionButtons(Composite composite) { Composite buttonsComposite = new Composite(composite, SWT.NONE); GridLayout layout = new GridLayout(); layout.marginWidth = 0; layout.marginHeight = 0; buttonsComposite.setLayout(layout); buttonsComposite.setLayoutData(new GridData( GridData.VERTICAL_ALIGN_BEGINNING)); Button selectAll = new Button(buttonsComposite, SWT.PUSH); selectAll.setText(ExportMessages.SelectAll); selectAll.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { for (int i = 0; i < mTableViewer.getTable().getItemCount(); i++) { mSelectedJavaProjects.add((IJavaProject) mTableViewer.getElementAt(i)); } mTableViewer.setAllChecked(true); updateEnablement(); } }); setButtonLayoutData(selectAll); Button deselectAll = new Button(buttonsComposite, SWT.PUSH); deselectAll.setText(ExportMessages.DeselectAll); deselectAll.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { mSelectedJavaProjects.clear(); mTableViewer.setAllChecked(false); updateEnablement(); } }); setButtonLayoutData(deselectAll); } /** * Populates the list with all the eligible projects in the workspace. */ private void initializeProjects() { IWorkspaceRoot rootWorkspace = ResourcesPlugin.getWorkspace().getRoot(); IJavaModel javaModel = JavaCore.create(rootWorkspace); IJavaProject[] javaProjects; try { javaProjects = javaModel.getJavaProjects(); } catch (JavaModelException e) { javaProjects = new IJavaProject[0]; } mTableViewer.setInput(javaProjects); // Check any necessary projects if (mSelectedJavaProjects != null) { mTableViewer.setCheckedElements(mSelectedJavaProjects.toArray( new IJavaProject[mSelectedJavaProjects.size()])); } } /** * Enables/disables the finish button on the wizard and displays error messages as needed. */ private void updateEnablement() { String error = null; try { if (mSelectedJavaProjects.size() == 0) { error = ExportMessages.NoProjectsError; return; } List cyclicProjects; try { cyclicProjects = getCyclicProjects(mSelectedJavaProjects); if (cyclicProjects.size() > 0) { error = MessageFormat.format(ExportMessages.CyclicProjectsError, new Object[] { Joiner.on(", ").join(cyclicProjects) }); //$NON-NLS-1$ return; } error = mBuilder.setProject(mSelectedJavaProjects); if (error != null) { return; } } catch (CoreException ignored) { // TODO: do something? } } finally { setErrorMessage(error); setPageComplete(error == null); getContainer().updateButtons(); } } @Override public void setVisible(boolean visible) { super.setVisible(visible); if (visible) { mTableViewer.getTable().setFocus(); mBuilder.setCanFinish(false); mBuilder.setCanGenerate(false); } } /** * Returns given projects that have cyclic dependencies. * * @param javaProjects list of IJavaProject objects * @return set of project names */ private List getCyclicProjects(List projects) throws CoreException { List cyclicProjects = new ArrayList(); for (IJavaProject javaProject : projects) { if (hasCyclicDependency(javaProject)) { cyclicProjects.add(javaProject.getProject().getName()); } } return cyclicProjects; } /** * Check if given project has a cyclic dependency. *

* See {@link org.eclipse.jdt.core.tests.model.ClasspathTests.numberOfCycleMarkers} */ private static boolean hasCyclicDependency(IJavaProject javaProject) throws CoreException { IMarker[] markers = javaProject.getProject().findMarkers( IJavaModelMarker.BUILDPATH_PROBLEM_MARKER, false, IResource.DEPTH_ONE); for (IMarker marker : markers) { String cycleAttr = (String) marker .getAttribute(IJavaModelMarker.CYCLE_DETECTED); if (cycleAttr != null && cycleAttr.equals("true")) { //$NON-NLS-1$ return true; } } return false; } }