Home | History | Annotate | Download | only in project
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Eclipse Public License, Version 1.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.eclipse.org/org/documents/epl-v10.php
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.ide.eclipse.adt.internal.project;
     18 
     19 import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper.IProjectFilter;
     20 import com.android.ide.eclipse.adt.internal.sdk.ProjectState;
     21 import com.android.ide.eclipse.adt.internal.sdk.Sdk;
     22 
     23 import org.eclipse.core.resources.IProject;
     24 import org.eclipse.core.resources.IWorkspaceRoot;
     25 import org.eclipse.core.resources.ResourcesPlugin;
     26 import org.eclipse.jdt.core.IJavaModel;
     27 import org.eclipse.jdt.core.IJavaProject;
     28 import org.eclipse.jdt.core.JavaCore;
     29 import org.eclipse.jdt.ui.JavaElementLabelProvider;
     30 import org.eclipse.jface.viewers.ILabelProvider;
     31 import org.eclipse.jface.window.Window;
     32 import org.eclipse.swt.SWT;
     33 import org.eclipse.swt.events.SelectionEvent;
     34 import org.eclipse.swt.events.SelectionListener;
     35 import org.eclipse.swt.widgets.Combo;
     36 import org.eclipse.swt.widgets.Composite;
     37 import org.eclipse.swt.widgets.Shell;
     38 import org.eclipse.ui.dialogs.ElementListSelectionDialog;
     39 
     40 /**
     41  * Helper class to deal with displaying a project choosing dialog that lists only the
     42  * projects with the Android nature.
     43  */
     44 public class ProjectChooserHelper {
     45 
     46     private final Shell mParentShell;
     47     private final IProjectChooserFilter mFilter;
     48 
     49     /**
     50      * List of current android projects. Since the dialog is modal, we'll just get
     51      * the list once on-demand.
     52      */
     53     private IJavaProject[] mAndroidProjects;
     54 
     55     /**
     56      * Interface to filter out some project displayed by {@link ProjectChooserHelper}.
     57      *
     58      * @see IProjectFilter
     59      */
     60     public interface IProjectChooserFilter extends IProjectFilter {
     61         /**
     62          * Whether the Project Chooser can compute the project list once and cache the result.
     63          * </p>If false the project list is recomputed every time the dialog is opened.
     64          */
     65         boolean useCache();
     66     }
     67 
     68     /**
     69      * An implementation of {@link IProjectChooserFilter} that only displays non-library projects.
     70      */
     71     public final static class NonLibraryProjectOnlyFilter implements IProjectChooserFilter {
     72         public boolean accept(IProject project) {
     73             ProjectState state = Sdk.getProjectState(project);
     74             if (state != null) {
     75                 return state.isLibrary() == false;
     76             }
     77 
     78             return false;
     79         }
     80 
     81         public boolean useCache() {
     82             return true;
     83         }
     84     }
     85 
     86     /**
     87      * An implementation of {@link IProjectChooserFilter} that only displays library projects.
     88      */
     89     public final static class LibraryProjectOnlyFilter implements IProjectChooserFilter {
     90         public boolean accept(IProject project) {
     91             ProjectState state = Sdk.getProjectState(project);
     92             if (state != null ) {
     93                 return state.isLibrary();
     94             }
     95 
     96             return false;
     97         }
     98 
     99         public boolean useCache() {
    100             return true;
    101         }
    102     }
    103 
    104     /**
    105      * Creates a new project chooser.
    106      * @param parentShell the parent {@link Shell} for the dialog.
    107      * @param filter a filter to only accept certain projects. Can be null.
    108      */
    109     public ProjectChooserHelper(Shell parentShell, IProjectChooserFilter filter) {
    110         mParentShell = parentShell;
    111         mFilter = filter;
    112     }
    113 
    114     /**
    115      * Displays a project chooser dialog which lists all available projects with the Android nature.
    116      * <p/>
    117      * The list of project is built from Android flagged projects currently opened in the workspace.
    118      *
    119      * @param projectName If non null and not empty, represents the name of an Android project
    120      *                    that will be selected by default.
    121      * @param message Message for the dialog box. Can be null in which case a default message
    122      *                is displayed.
    123      * @return the project chosen by the user in the dialog, or null if the dialog was canceled.
    124      */
    125     public IJavaProject chooseJavaProject(String projectName, String message) {
    126         ILabelProvider labelProvider = new JavaElementLabelProvider(
    127                 JavaElementLabelProvider.SHOW_DEFAULT);
    128         ElementListSelectionDialog dialog = new ElementListSelectionDialog(
    129                 mParentShell, labelProvider);
    130         dialog.setTitle("Project Selection");
    131         if (message == null) {
    132             message = "Please select a project";
    133         }
    134         dialog.setMessage(message);
    135 
    136         IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
    137         IJavaModel javaModel = JavaCore.create(workspaceRoot);
    138 
    139         // set the elements in the dialog. These are opened android projects.
    140         dialog.setElements(getAndroidProjects(javaModel));
    141 
    142         // look for the project matching the given project name
    143         IJavaProject javaProject = null;
    144         if (projectName != null && projectName.length() > 0) {
    145             javaProject = javaModel.getJavaProject(projectName);
    146         }
    147 
    148         // if we found it, we set the initial selection in the dialog to this one.
    149         if (javaProject != null) {
    150             dialog.setInitialSelections(new Object[] { javaProject });
    151         }
    152 
    153         // open the dialog and return the object selected if OK was clicked, or null otherwise
    154         if (dialog.open() == Window.OK) {
    155             return (IJavaProject) dialog.getFirstResult();
    156         }
    157         return null;
    158     }
    159 
    160     /**
    161      * Returns the list of Android projects.
    162      * <p/>
    163      * Because this list can be time consuming, this class caches the list of project.
    164      * It is recommended to call this method instead of
    165      * {@link BaseProjectHelper#getAndroidProjects()}.
    166      *
    167      * @param javaModel the java model. Can be null.
    168      */
    169     public IJavaProject[] getAndroidProjects(IJavaModel javaModel) {
    170         // recompute only if we don't have the projects already or the filter is dynamic
    171         // and prevent usage of a cache.
    172         if (mAndroidProjects == null || (mFilter != null && mFilter.useCache() == false)) {
    173             if (javaModel == null) {
    174                 mAndroidProjects = BaseProjectHelper.getAndroidProjects(mFilter);
    175             } else {
    176                 mAndroidProjects = BaseProjectHelper.getAndroidProjects(javaModel, mFilter);
    177             }
    178         }
    179 
    180         return mAndroidProjects;
    181     }
    182 
    183     /**
    184      * Helper method to get the Android project with the given name
    185      *
    186      * @param projectName the name of the project to find
    187      * @return the {@link IProject} for the Android project. <code>null</code> if not found.
    188      */
    189     public IProject getAndroidProject(String projectName) {
    190         IProject iproject = null;
    191         IJavaProject[] javaProjects = getAndroidProjects(null);
    192         if (javaProjects != null) {
    193             for (IJavaProject javaProject : javaProjects) {
    194                 if (javaProject.getElementName().equals(projectName)) {
    195                     iproject = javaProject.getProject();
    196                     break;
    197                 }
    198             }
    199         }
    200         return iproject;
    201     }
    202 
    203     /**
    204      * A selector combo for showing the currently selected project and for
    205      * changing the selection
    206      */
    207     public static class ProjectCombo extends Combo implements SelectionListener {
    208         /** Currently chosen project, or null when no project has been initialized or selected */
    209         private IProject mProject;
    210         private IJavaProject[] mAvailableProjects;
    211 
    212         /**
    213          * Creates a new project selector combo
    214          *
    215          * @param helper associated {@link ProjectChooserHelper} for looking up
    216          *            projects
    217          * @param parent parent composite to add the combo to
    218          * @param initialProject the initial project to select, or null (which
    219          *            will show a "Please Choose Project..." label instead.)
    220          */
    221         public ProjectCombo(ProjectChooserHelper helper, Composite parent,
    222                 IProject initialProject) {
    223             super(parent, SWT.BORDER | SWT.FLAT | SWT.READ_ONLY);
    224             mProject = initialProject;
    225 
    226             mAvailableProjects = helper.getAndroidProjects(null);
    227             String[] items = new String[mAvailableProjects.length + 1];
    228             items[0] = "--- Choose Project ---";
    229 
    230             ILabelProvider labelProvider = new JavaElementLabelProvider(
    231                     JavaElementLabelProvider.SHOW_DEFAULT);
    232             int selectionIndex = 0;
    233             for (int i = 0, n = mAvailableProjects.length; i < n; i++) {
    234                 IProject project = mAvailableProjects[i].getProject();
    235                 items[i + 1] = labelProvider.getText(project);
    236                 if (project == initialProject) {
    237                     selectionIndex = i + 1;
    238                 }
    239             }
    240             setItems(items);
    241             select(selectionIndex);
    242 
    243             addSelectionListener(this);
    244         }
    245 
    246         /**
    247          * Returns the project selected by this chooser (or the initial project
    248          * passed to the constructor if the user did not change it)
    249          *
    250          * @return the selected project
    251          */
    252         public IProject getSelectedProject() {
    253             return mProject;
    254         }
    255 
    256         /**
    257          * Sets the project selected by this chooser
    258          *
    259          * @param project the selected project
    260          */
    261         public void setSelectedProject(IProject project) {
    262             mProject = project;
    263 
    264             int selectionIndex = 0;
    265             for (int i = 0, n = mAvailableProjects.length; i < n; i++) {
    266                 if (project == mAvailableProjects[i].getProject()) {
    267                     selectionIndex = i + 1; // +1: Slot 0 is reserved for "Choose Project"
    268                     select(selectionIndex);
    269                     break;
    270                 }
    271             }
    272         }
    273 
    274         /**
    275          * Click handler for the button: Open the {@link ProjectChooserHelper}
    276          * dialog for selecting a new project.
    277          */
    278         public void widgetSelected(SelectionEvent e) {
    279             int selectionIndex = getSelectionIndex();
    280             if (selectionIndex > 0 && mAvailableProjects != null
    281                     && selectionIndex <= mAvailableProjects.length) {
    282                 // selection index 0 is "Choose Project", all other projects are offset
    283                 // by 1 from the selection index
    284                 mProject = mAvailableProjects[selectionIndex - 1].getProject();
    285             } else {
    286                 mProject = null;
    287             }
    288         }
    289 
    290         public void widgetDefaultSelected(SelectionEvent e) {
    291         }
    292 
    293         @Override
    294         protected void checkSubclass() {
    295             // Disable the check that prevents subclassing of SWT components
    296         }
    297     }
    298 }
    299