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