Home | History | Annotate | Download | only in project
      1 /*
      2  * Copyright (C) 2012 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 static com.android.SdkConstants.FQCN_GRID_LAYOUT;
     20 import static com.android.SdkConstants.FQCN_GRID_LAYOUT_V7;
     21 import static com.android.SdkConstants.FQCN_SPACE;
     22 import static com.android.SdkConstants.FQCN_SPACE_V7;
     23 
     24 import com.android.annotations.NonNull;
     25 import com.android.annotations.Nullable;
     26 import com.android.ide.eclipse.adt.AdtUtils;
     27 import com.android.ide.eclipse.adt.internal.actions.AddSupportJarAction;
     28 import com.android.ide.eclipse.adt.internal.editors.manifest.ManifestInfo;
     29 import com.android.ide.eclipse.adt.internal.sdk.ProjectState;
     30 import com.android.ide.eclipse.adt.internal.sdk.ProjectState.LibraryState;
     31 import com.android.ide.eclipse.adt.internal.sdk.Sdk;
     32 
     33 import org.eclipse.core.resources.IProject;
     34 import org.eclipse.jdt.core.IJavaProject;
     35 import org.eclipse.jface.dialogs.MessageDialog;
     36 import org.eclipse.swt.widgets.Display;
     37 
     38 /**
     39  * Helper class for the Android Support Library. The support library provides
     40  * (for example) a backport of GridLayout, which must be used as a library
     41  * project rather than a jar library since it has resources. This class provides
     42  * support for finding the library project, or downloading and installing it on
     43  * demand if it does not, as well as translating tags such as
     44  * {@code <GridLayout>} into {@code <com.android.support.v7.GridLayout>} if it
     45  * does not.
     46  */
     47 public class SupportLibraryHelper {
     48     /**
     49      * Returns the correct tag to use for the given view tag. This is normally
     50      * the same as the tag itself. However, for some views which are not available
     51      * on all platforms, this will:
     52      * <ul>
     53      *  <li> Check if the view is available in the compatibility library,
     54      *       and if so, if the support library is not installed, will offer to
     55      *       install it via the SDK manager.
     56      *  <li> (The tool may also offer to adjust the minimum SDK of the project
     57      *       up to a level such that the given tag is supported directly, and then
     58      *       this method will return the original tag.)
     59      *  <li> Check whether the compatibility library is included in the project, and
     60      *       if not, offer to copy it into the workspace and add a library dependency.
     61      *  <li> Return the alternative tag. For example, for "GridLayout", it will
     62      *       (if the minimum SDK is less than 14) return "com.android.support.v7.GridLayout"
     63      *       instead.
     64      * </ul>
     65      *
     66      * @param project the project to add the dependency into
     67      * @param tag the tag to look up, such as "GridLayout"
     68      * @return the tag to use in the layout, normally the same as the input tag but possibly
     69      *      an equivalent compatibility library tag instead.
     70      */
     71     @NonNull
     72     public static String getTagFor(@NonNull IProject project, @NonNull String tag) {
     73         boolean isGridLayout = tag.equals(FQCN_GRID_LAYOUT);
     74         boolean isSpace = tag.equals(FQCN_SPACE);
     75         if (isGridLayout || isSpace) {
     76             int minSdk = ManifestInfo.get(project).getMinSdkVersion();
     77             if (minSdk < 14) {
     78                 // See if the support library is installed in the SDK area
     79                 // See if there is a local project in the workspace providing the
     80                 // project
     81                 IProject supportProject = getSupportProjectV7();
     82                 if (supportProject != null) {
     83                     // Make sure I have a dependency on it
     84                     ProjectState state = Sdk.getProjectState(project);
     85                     if (state != null) {
     86                         for (LibraryState library : state.getLibraries()) {
     87                             if (supportProject.equals(library.getProjectState().getProject())) {
     88                                 // Found it: you have the compatibility library and have linked
     89                                 // to it: use the alternative tag
     90                                 return isGridLayout ? FQCN_GRID_LAYOUT_V7 : FQCN_SPACE_V7;
     91                             }
     92                         }
     93                     }
     94                 }
     95 
     96                 // Ask user to install it
     97                 String message = String.format(
     98                         "%1$s requires API level 14 or higher, or a compatibility "
     99                                 + "library for older versions.\n\n"
    100                                 + " Do you want to install the compatibility library?", tag);
    101                 MessageDialog dialog =
    102                         new MessageDialog(
    103                                 Display.getCurrent().getActiveShell(),
    104                                 "Warning",
    105                                 null,
    106                                 message,
    107                                 MessageDialog.QUESTION,
    108                                 new String[] {
    109                                         "Install", "Cancel"
    110                                 },
    111                                 1 /* default button: Cancel */);
    112                 int answer = dialog.open();
    113                 if (answer == 0) {
    114                     if (supportProject != null) {
    115                         // Just add library dependency
    116                         if (!AddSupportJarAction.addLibraryDependency(
    117                                 supportProject,
    118                                 project,
    119                                 true /* waitForFinish */)) {
    120                             return tag;
    121                         }
    122                     } else {
    123                         // Install library AND add dependency
    124                         if (!AddSupportJarAction.installGridLayoutLibrary(
    125                                 project,
    126                                 true /* waitForFinish */)) {
    127                             return tag;
    128                         }
    129                     }
    130 
    131                     return isGridLayout ? FQCN_GRID_LAYOUT_V7 : FQCN_SPACE_V7;
    132                 }
    133             }
    134         }
    135 
    136         return tag;
    137     }
    138 
    139     /** Cache for {@link #getSupportProjectV7()} */
    140     private static IProject sCachedProject;
    141 
    142     /**
    143      * Finds and returns the support project in the workspace, if any.
    144      *
    145      * @return the android support library project, or null if not found
    146      */
    147     @Nullable
    148     public static IProject getSupportProjectV7() {
    149         if (sCachedProject != null) {
    150             if (sCachedProject.isAccessible()) {
    151                 return sCachedProject;
    152             } else {
    153                 sCachedProject = null;
    154             }
    155         }
    156 
    157         sCachedProject = findSupportProjectV7();
    158         return sCachedProject;
    159     }
    160 
    161     @Nullable
    162     private static IProject findSupportProjectV7() {
    163         for (IJavaProject javaProject : AdtUtils.getOpenAndroidProjects()) {
    164             IProject project = javaProject.getProject();
    165             ProjectState state = Sdk.getProjectState(project);
    166             if (state != null && state.isLibrary()) {
    167                 ManifestInfo manifestInfo = ManifestInfo.get(project);
    168                 if (manifestInfo.getPackage().equals("android.support.v7.gridlayout")) { //$NON-NLS-1$
    169                     return project;
    170                 }
    171             }
    172         }
    173 
    174         return null;
    175     }
    176 }
    177