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 */ useCache()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 accept(IProject project)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 useCache()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 accept(IProject project)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 useCache()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 */ ProjectChooserHelper(Shell parentShell, IProjectChooserFilter filter)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 */ chooseJavaProject(String projectName, String message)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 */ getAndroidProjects(IJavaModel javaModel)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 */ getAndroidProject(String projectName)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 */ ProjectCombo(ProjectChooserHelper helper, Composite parent, IProject initialProject)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 */ getSelectedProject()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 */ setSelectedProject(IProject project)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 widgetSelected(SelectionEvent e)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 widgetDefaultSelected(SelectionEvent e)296 public void widgetDefaultSelected(SelectionEvent e) { 297 } 298 299 @Override checkSubclass()300 protected void checkSubclass() { 301 // Disable the check that prevents subclassing of SWT components 302 } 303 } 304 } 305