| /* |
| * 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; |
| } |
| } |