blob: 81c7a73465db8325a9f1401420dad217aa04d240 [file] [log] [blame]
/*
* 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.
* <p>
* Based on {@link org.eclipse.ant.internal.ui.datatransfer.AntBuildfileExportPage}
*/
public class ProjectSelectionPage extends WizardPage {
private final ProjectSetupBuilder mBuilder;
private CheckboxTableViewer mTableViewer;
private List<IJavaProject> 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<String> 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<String> getCyclicProjects(List<IJavaProject> projects) throws CoreException {
List<String> cyclicProjects = new ArrayList<String>();
for (IJavaProject javaProject : projects) {
if (hasCyclicDependency(javaProject)) {
cyclicProjects.add(javaProject.getProject().getName());
}
}
return cyclicProjects;
}
/**
* Check if given project has a cyclic dependency.
* <p>
* 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;
}
}