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 package com.android.ide.eclipse.adt.internal.wizards.templates;
17 
18 import com.android.ide.eclipse.adt.AdtPlugin;
19 import com.android.ide.eclipse.adt.internal.actions.AddSupportJarAction;
20 import com.android.utils.Pair;
21 
22 import org.eclipse.core.runtime.IStatus;
23 import org.eclipse.core.runtime.Status;
24 import org.eclipse.jface.dialogs.IMessageProvider;
25 import org.eclipse.jface.dialogs.MessageDialog;
26 import org.eclipse.jface.wizard.IWizard;
27 import org.eclipse.jface.wizard.IWizardPage;
28 import org.eclipse.jface.wizard.WizardPage;
29 import org.eclipse.swt.SWT;
30 import org.eclipse.swt.events.SelectionEvent;
31 import org.eclipse.swt.events.SelectionListener;
32 import org.eclipse.swt.layout.GridData;
33 import org.eclipse.swt.layout.GridLayout;
34 import org.eclipse.swt.widgets.Button;
35 import org.eclipse.swt.widgets.Composite;
36 import org.eclipse.swt.widgets.Label;
37 import org.eclipse.swt.widgets.Link;
38 import org.eclipse.ui.IWorkbench;
39 import org.eclipse.ui.PlatformUI;
40 import org.eclipse.ui.browser.IWebBrowser;
41 
42 import java.io.File;
43 import java.net.URL;
44 import java.util.List;
45 
46 class InstallDependencyPage extends WizardPage implements SelectionListener {
47     /**
48      * The compatibility library. This is the only library the templates
49      * currently support. The appearance of any other dependency in this
50      * template will be flagged as a validation error (and the user encouraged
51      * to upgrade to a newer ADT
52      */
53     static final String SUPPORT_LIBRARY_NAME = "android-support-v4"; //$NON-NLS-1$
54 
55     /** URL containing more info */
56     private static final String URL =
57             "http://developer.android.com/tools/extras/support-library.html"; //$NON-NLS-1$
58 
59     private Button mCheckButton;
60     private Button mInstallButton;
61     private Link mLink;
62     private TemplateMetadata mTemplate;
63 
InstallDependencyPage()64     InstallDependencyPage() {
65         super("dependency"); //$NON-NLS-1$
66         setTitle("Install Dependencies");
67     }
68 
setTemplate(TemplateMetadata template)69     void setTemplate(TemplateMetadata template) {
70         if (template != mTemplate) {
71             mTemplate = template;
72             if (getControl() != null) {
73                 validatePage();
74             }
75         }
76     }
77 
78     @Override
setVisible(boolean visible)79     public void setVisible(boolean visible) {
80         super.setVisible(visible);
81         if (visible) {
82             updateVersionLabels();
83             validatePage();
84         }
85     }
86 
87     @Override
createControl(Composite parent)88     public void createControl(Composite parent) {
89         Composite container = new Composite(parent, SWT.NULL);
90         setControl(container);
91         container.setLayout(new GridLayout(2, false));
92         // Remaining contents are created lazily, since this page is always added to
93         // the page list, but typically not shown
94 
95         Label dependLabel = new Label(container, SWT.WRAP);
96         GridData gd_dependLabel = new GridData(SWT.LEFT, SWT.TOP, true, false, 2, 1);
97         gd_dependLabel.widthHint = NewTemplatePage.WIZARD_PAGE_WIDTH - 50;
98         dependLabel.setLayoutData(gd_dependLabel);
99         dependLabel.setText("This template depends on the Android Support library, which is " +
100                 "either not installed, or the template depends on a more recent version than " +
101                 "the one you have installed.");
102 
103         mLink = new Link(container, SWT.NONE);
104         mLink.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false, 2, 1));
105         mLink.setText("<a href=\"" + URL + "\">" + URL + "</a>"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
106         mLink.addSelectionListener(this);
107 
108         Label lblNewLabel_1 = new Label(container, SWT.NONE);
109         lblNewLabel_1.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1));
110 
111         requiredLabel = new Label(container, SWT.NONE);
112         requiredLabel.setText("Required version:");
113 
114         mRequiredVersion = new Label(container, SWT.NONE);
115         mRequiredVersion.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
116 
117         installedLabel = new Label(container, SWT.NONE);
118         installedLabel.setText("Installed version:");
119 
120         mInstalledVersion = new Label(container, SWT.NONE);
121         mInstalledVersion.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
122 
123         Label lblNewLabel = new Label(container, SWT.NONE);
124         lblNewLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1));
125 
126         Label descLabel = new Label(container, SWT.WRAP);
127         GridData gd_descLabel = new GridData(SWT.LEFT, SWT.TOP, true, false, 2, 1);
128         gd_descLabel.widthHint = 550;
129         descLabel.setLayoutData(gd_descLabel);
130         descLabel.setText(
131                 "You can install or upgrade it by clicking the Install button below, or " +
132                 "alternatively, you can install it outside of Eclipse with the SDK Manager, " +
133                 "then click on \"Check Again\" to proceed.");
134 
135         mInstallButton = new Button(container, SWT.NONE);
136         mInstallButton.setText("Install/Upgrade");
137         mInstallButton.addSelectionListener(this);
138 
139         mCheckButton = new Button(container, SWT.NONE);
140         mCheckButton.setText("Check Again");
141         mCheckButton.addSelectionListener(this);
142 
143         mInstallButton.setFocus();
144     }
145 
showNextPage()146     private void showNextPage() {
147         validatePage();
148         if (isPageComplete()) {
149             // Finish button will be enabled now
150             mInstallButton.setEnabled(false);
151             mCheckButton.setEnabled(false);
152 
153             IWizard wizard = getWizard();
154             IWizardPage next = wizard.getNextPage(this);
155             if (next != null) {
156                 wizard.getContainer().showPage(next);
157             }
158         }
159     }
160 
161     @Override
isPageComplete()162     public boolean isPageComplete() {
163         if (mTemplate == null) {
164             return true;
165         }
166 
167         return super.isPageComplete() && isInstalled();
168     }
169 
isInstalled()170     private boolean isInstalled() {
171         return isInstalled(mTemplate.getDependencies());
172     }
173 
174     static String sCachedName;
175     static int sCachedVersion;
176     private Label requiredLabel;
177     private Label installedLabel;
178     private Label mRequiredVersion;
179     private Label mInstalledVersion;
180 
isInstalled(List<Pair<String, Integer>> dependencies)181     public static boolean isInstalled(List<Pair<String, Integer>> dependencies) {
182         for (Pair<String, Integer> dependency : dependencies) {
183             String name = dependency.getFirst();
184             int required = dependency.getSecond();
185 
186             int installed = -1;
187             if (SUPPORT_LIBRARY_NAME.equals(name)) {
188                 installed = getInstalledSupportLibVersion();
189             }
190 
191             if (installed == -1) {
192                 return false;
193             }
194             if (required > installed) {
195                 return false;
196             }
197         }
198 
199         return true;
200     }
201 
getInstalledSupportLibVersion()202     private static int getInstalledSupportLibVersion() {
203         if (SUPPORT_LIBRARY_NAME.equals(sCachedName)) {
204             return sCachedVersion;
205         } else {
206             int version = AddSupportJarAction.getInstalledRevision();
207             sCachedName = SUPPORT_LIBRARY_NAME;
208             sCachedVersion = version;
209             return version;
210         }
211     }
212 
updateVersionLabels()213     private void updateVersionLabels() {
214         int version = getInstalledSupportLibVersion();
215         if (version == -1) {
216             mInstalledVersion.setText("Not installed");
217         } else {
218             mInstalledVersion.setText(Integer.toString(version));
219         }
220 
221         if (mTemplate != null) {
222             for (Pair<String, Integer> dependency : mTemplate.getDependencies()) {
223                 String name = dependency.getFirst();
224                 if (name.equals(SUPPORT_LIBRARY_NAME)) {
225                     int required = dependency.getSecond();
226                     mRequiredVersion.setText(Integer.toString(required));
227                     break;
228                 }
229             }
230         }
231     }
232 
validatePage()233     private void validatePage() {
234         if (mTemplate == null) {
235             return;
236         }
237 
238         IStatus status = null;
239 
240         List<Pair<String, Integer>> dependencies = mTemplate.getDependencies();
241         if (dependencies.size() > 1 || dependencies.size() == 1
242                 && !dependencies.get(0).getFirst().equals(SUPPORT_LIBRARY_NAME)) {
243             status = new Status(IStatus.WARNING, AdtPlugin.PLUGIN_ID,
244                     "Unsupported template dependency: Upgrade your Android Eclipse plugin");
245         }
246 
247         setPageComplete(status == null || status.getSeverity() != IStatus.ERROR);
248         if (status != null) {
249             setMessage(status.getMessage(),
250                     status.getSeverity() == IStatus.ERROR
251                         ? IMessageProvider.ERROR : IMessageProvider.WARNING);
252         } else {
253             setErrorMessage(null);
254             setMessage(null);
255         }
256     }
257 
258     // ---- Implements SelectionListener ----
259 
260     @Override
widgetSelected(SelectionEvent e)261     public void widgetSelected(SelectionEvent e) {
262         Object source = e.getSource();
263         if (source == mCheckButton) {
264             sCachedName = null;
265             if (isInstalled()) {
266                 showNextPage();
267             }
268             updateVersionLabels();
269         } else if (source == mInstallButton) {
270             sCachedName = null;
271             for (Pair<String, Integer> dependency : mTemplate.getDependencies()) {
272                 String name = dependency.getFirst();
273                 if (SUPPORT_LIBRARY_NAME.equals(name)) {
274                     int version = dependency.getSecond();
275                     File installed = AddSupportJarAction.installSupport(version);
276                     if (installed != null) {
277                         showNextPage();
278                     }
279                     updateVersionLabels();
280                 }
281             }
282         } else if (source == mLink) {
283             try {
284                 IWorkbench workbench = PlatformUI.getWorkbench();
285                 IWebBrowser browser = workbench.getBrowserSupport().getExternalBrowser();
286                 browser.openURL(new URL(URL));
287             } catch (Exception ex) {
288                 String message = String.format("Could not open browser. Vist\n%1$s\ninstead.",
289                         URL);
290                 MessageDialog.openError(getShell(), "Browser Error", message);
291             }
292         }
293     }
294 
295     @Override
widgetDefaultSelected(SelectionEvent e)296     public void widgetDefaultSelected(SelectionEvent e) {
297     }
298 }
299