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         @Override
     73         public boolean accept(IProject project) {
     74             ProjectState state = Sdk.getProjectState(project);
     75             if (state != null) {
     76                 return state.isLibrary() == false;
     77             }
     78 
     79             return false;
     80         }
     81 
     82         @Override
     83         public boolean useCache() {
     84             return true;
     85         }
     86     }
     87 
     88     /**
     89      * An implementation of {@link IProjectChooserFilter} that only displays library projects.
     90      */
     91     public final static class LibraryProjectOnlyFilter implements IProjectChooserFilter {
     92         @Override
     93         public boolean accept(IProject project) {
     94             ProjectState state = Sdk.getProjectState(project);
     95             if (state != null ) {
     96                 return state.isLibrary();
     97             }
     98 
     99             return false;
    100         }
    101 
    102         @Override
    103         public boolean useCache() {
    104             return true;
    105         }
    106     }
    107 
    108     /**
    109      * Creates a new project chooser.
    110      * @param parentShell the parent {@link Shell} for the dialog.
    111      * @param filter a filter to only accept certain projects. Can be null.
    112      */
    113     public ProjectChooserHelper(Shell parentShell, IProjectChooserFilter filter) {
    114         mParentShell = parentShell;
    115         mFilter = filter;
    116     }
    117 
    118     /**
    119      * Displays a project chooser dialog which lists all available projects with the Android nature.
    120      * <p/>
    121      * The list of project is built from Android flagged projects currently opened in the workspace.
    122      *
    123      * @param projectName If non null and not empty, represents the name of an Android project
    124      *                    that will be selected by default.
    125      * @param message Message for the dialog box. Can be null in which case a default message
    126      *                is displayed.
    127      * @return the project chosen by the user in the dialog, or null if the dialog was canceled.
    128      */
    129     public IJavaProject chooseJavaProject(String projectName, String message) {
    130         ILabelProvider labelProvider = new JavaElementLabelProvider(
    131                 JavaElementLabelProvider.SHOW_DEFAULT);
    132         ElementListSelectionDialog dialog = new ElementListSelectionDialog(
    133                 mParentShell, labelProvider);
    134         dialog.setTitle("Project Selection");
    135         if (message == null) {
    136             message = "Please select a project";
    137         }
    138         dialog.setMessage(message);
    139 
    140         IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
    141         IJavaModel javaModel = JavaCore.create(workspaceRoot);
    142 
    143         // set the elements in the dialog. These are opened android projects.
    144         dialog.setElements(getAndroidProjects(javaModel));
    145 
    146         // look for the project matching the given project name
    147         IJavaProject javaProject = null;
    148         if (projectName != null && projectName.length() > 0) {
    149             javaProject = javaModel.getJavaProject(projectName);
    150         }
    151 
    152         // if we found it, we set the initial selection in the dialog to this one.
    153         if (javaProject != null) {
    154             dialog.setInitialSelections(new Object[] { javaProject });
    155         }
    156 
    157         // open the dialog and return the object selected if OK was clicked, or null otherwise
    158         if (dialog.open() == Window.OK) {
    159             return (IJavaProject) dialog.getFirstResult();
    160         }
    161         return null;
    162     }
    163 
    164     /**
    165      * Returns the list of Android projects.
    166      * <p/>
    167      * Because this list can be time consuming, this class caches the list of project.
    168      * It is recommended to call this method instead of
    169      * {@link BaseProjectHelper#getAndroidProjects()}.
    170      *
    171      * @param javaModel the java model. Can be null.
    172      */
    173     public IJavaProject[] getAndroidProjects(IJavaModel javaModel) {
    174         // recompute only if we don't have the projects already or the filter is dynamic
    175         // and prevent usage of a cache.
    176         if (mAndroidProjects == null || (mFilter != null && mFilter.useCache() == false)) {
    177             if (javaModel == null) {
    178                 mAndroidProjects = BaseProjectHelper.getAndroidProjects(mFilter);
    179             } else {
    180                 mAndroidProjects = BaseProjectHelper.getAndroidProjects(javaModel, mFilter);
    181             }
    182         }
    183 
    184         return mAndroidProjects;
    185     }
    186 
    187     /**
    188      * Helper method to get the Android project with the given name
    189      *
    190      * @param projectName the name of the project to find
    191      * @return the {@link IProject} for the Android project. <code>null</code> if not found.
    192      */
    193     public IProject getAndroidProject(String projectName) {
    194         IProject iproject = null;
    195         IJavaProject[] javaProjects = getAndroidProjects(null);
    196         if (javaProjects != null) {
    197             for (IJavaProject javaProject : javaProjects) {
    198                 if (javaProject.getElementName().equals(projectName)) {
    199                     iproject = javaProject.getProject();
    200                     break;
    201                 }
    202             }
    203         }
    204         return iproject;
    205     }
    206 
    207     /**
    208      * A selector combo for showing the currently selected project and for
    209      * changing the selection
    210      */
    211     public static class ProjectCombo extends Combo implements SelectionListener {
    212         /** Currently chosen project, or null when no project has been initialized or selected */
    213         private IProject mProject;
    214         private IJavaProject[] mAvailableProjects;
    215 
    216         /**
    217          * Creates a new project selector combo
    218          *
    219          * @param helper associated {@link ProjectChooserHelper} for looking up
    220          *            projects
    221          * @param parent parent composite to add the combo to
    222          * @param initialProject the initial project to select, or null (which
    223          *            will show a "Please Choose Project..." label instead.)
    224          */
    225         public ProjectCombo(ProjectChooserHelper helper, Composite parent,
    226                 IProject initialProject) {
    227             super(parent, SWT.BORDER | SWT.FLAT | SWT.READ_ONLY);
    228             mProject = initialProject;
    229 
    230             mAvailableProjects = helper.getAndroidProjects(null);
    231             String[] items = new String[mAvailableProjects.length + 1];
    232             items[0] = "--- Choose Project ---";
    233 
    234             ILabelProvider labelProvider = new JavaElementLabelProvider(
    235                     JavaElementLabelProvider.SHOW_DEFAULT);
    236             int selectionIndex = 0;
    237             for (int i = 0, n = mAvailableProjects.length; i < n; i++) {
    238                 IProject project = mAvailableProjects[i].getProject();
    239                 items[i + 1] = labelProvider.getText(project);
    240                 if (project == initialProject) {
    241                     selectionIndex = i + 1;
    242                 }
    243             }
    244             setItems(items);
    245             select(selectionIndex);
    246 
    247             addSelectionListener(this);
    248         }
    249 
    250         /**
    251          * Returns the project selected by this chooser (or the initial project
    252          * passed to the constructor if the user did not change it)
    253          *
    254          * @return the selected project
    255          */
    256         public IProject getSelectedProject() {
    257             return mProject;
    258         }
    259 
    260         /**
    261          * Sets the project selected by this chooser
    262          *
    263          * @param project the selected project
    264          */
    265         public void setSelectedProject(IProject project) {
    266             mProject = project;
    267 
    268             int selectionIndex = 0;
    269             for (int i = 0, n = mAvailableProjects.length; i < n; i++) {
    270                 if (project == mAvailableProjects[i].getProject()) {
    271                     selectionIndex = i + 1; // +1: Slot 0 is reserved for "Choose Project"
    272                     select(selectionIndex);
    273                     break;
    274                 }
    275             }
    276         }
    277 
    278         /**
    279          * Click handler for the button: Open the {@link ProjectChooserHelper}
    280          * dialog for selecting a new project.
    281          */
    282         @Override
    283         public void widgetSelected(SelectionEvent e) {
    284             int selectionIndex = getSelectionIndex();
    285             if (selectionIndex > 0 && mAvailableProjects != null
    286                     && selectionIndex <= mAvailableProjects.length) {
    287                 // selection index 0 is "Choose Project", all other projects are offset
    288                 // by 1 from the selection index
    289                 mProject = mAvailableProjects[selectionIndex - 1].getProject();
    290             } else {
    291                 mProject = null;
    292             }
    293         }
    294 
    295         @Override
    296         public void widgetDefaultSelected(SelectionEvent e) {
    297         }
    298 
    299         @Override
    300         protected void checkSubclass() {
    301             // Disable the check that prevents subclassing of SWT components
    302         }
    303     }
    304 }
    305