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 */
16package com.android.ide.eclipse.adt.internal.wizards.templates;
17
18import com.android.ide.eclipse.adt.AdtPlugin;
19import com.android.ide.eclipse.adt.internal.actions.AddSupportJarAction;
20import com.android.utils.Pair;
21
22import org.eclipse.core.runtime.IStatus;
23import org.eclipse.core.runtime.Status;
24import org.eclipse.jface.dialogs.IMessageProvider;
25import org.eclipse.jface.dialogs.MessageDialog;
26import org.eclipse.jface.wizard.IWizard;
27import org.eclipse.jface.wizard.IWizardPage;
28import org.eclipse.jface.wizard.WizardPage;
29import org.eclipse.swt.SWT;
30import org.eclipse.swt.events.SelectionEvent;
31import org.eclipse.swt.events.SelectionListener;
32import org.eclipse.swt.layout.GridData;
33import org.eclipse.swt.layout.GridLayout;
34import org.eclipse.swt.widgets.Button;
35import org.eclipse.swt.widgets.Composite;
36import org.eclipse.swt.widgets.Label;
37import org.eclipse.swt.widgets.Link;
38import org.eclipse.ui.IWorkbench;
39import org.eclipse.ui.PlatformUI;
40import org.eclipse.ui.browser.IWebBrowser;
41
42import java.io.File;
43import java.net.URL;
44import java.util.List;
45
46class 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
64    InstallDependencyPage() {
65        super("dependency"); //$NON-NLS-1$
66        setTitle("Install Dependencies");
67    }
68
69    void setTemplate(TemplateMetadata template) {
70        if (template != mTemplate) {
71            mTemplate = template;
72            if (getControl() != null) {
73                validatePage();
74            }
75        }
76    }
77
78    @Override
79    public void setVisible(boolean visible) {
80        super.setVisible(visible);
81        if (visible) {
82            updateVersionLabels();
83            validatePage();
84        }
85    }
86
87    @Override
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
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
162    public boolean isPageComplete() {
163        if (mTemplate == null) {
164            return true;
165        }
166
167        return super.isPageComplete() && isInstalled();
168    }
169
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
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
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
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
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
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
296    public void widgetDefaultSelected(SelectionEvent e) {
297    }
298}
299