com.android.ide.eclipse.adt.internal.wizards.exportgradle.ProjectSelectionPage.java Source code

Java tutorial

Introduction

Here is the source code for com.android.ide.eclipse.adt.internal.wizards.exportgradle.ProjectSelectionPage.java

Source

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