170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll/*
270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll * Copyright (C) 2011 The Android Open Source Project
370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll *
470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll * Licensed under the Apache License, Version 2.0 (the "License");
570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll * you may not use this file except in compliance with the License.
670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll * You may obtain a copy of the License at
770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll *
870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll *      http://www.apache.org/licenses/LICENSE-2.0
970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll *
1070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll * Unless required by applicable law or agreed to in writing, software
1170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll * distributed under the License is distributed on an "AS IS" BASIS,
1270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll * See the License for the specific language governing permissions and
1470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll * limitations under the License.
1570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll */
1670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
17e46e7023069558853aad42f569a4d3fe6249d099Raphael Mollpackage com.android.sdkuilib.internal.repository.ui;
1870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
1970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
2081cefe2a26dd6db8a878e30874d12cdcbff0e83bXavier Ducrohetimport com.android.SdkConstants;
2170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Mollimport com.android.sdklib.internal.repository.ITaskFactory;
2270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Mollimport com.android.sdklib.internal.repository.sources.SdkSourceProperties;
2370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Mollimport com.android.sdkuilib.internal.repository.AboutDialog;
2470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Mollimport com.android.sdkuilib.internal.repository.ISdkUpdaterWindow;
2570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Mollimport com.android.sdkuilib.internal.repository.MenuBarWrapper;
2670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Mollimport com.android.sdkuilib.internal.repository.SettingsController;
2770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Mollimport com.android.sdkuilib.internal.repository.SettingsController.Settings;
2870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Mollimport com.android.sdkuilib.internal.repository.SettingsDialog;
2970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Mollimport com.android.sdkuilib.internal.repository.UpdaterData;
3070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Mollimport com.android.sdkuilib.internal.repository.icons.ImageFactory;
31e46e7023069558853aad42f569a4d3fe6249d099Raphael Mollimport com.android.sdkuilib.internal.repository.ui.PackagesPage.MenuAction;
3270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Mollimport com.android.sdkuilib.internal.tasks.ILogUiProvider;
3370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Mollimport com.android.sdkuilib.internal.tasks.ProgressView;
3470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Mollimport com.android.sdkuilib.internal.tasks.ProgressViewFactory;
3570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Mollimport com.android.sdkuilib.internal.widgets.ImgDisabledButton;
3670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Mollimport com.android.sdkuilib.internal.widgets.ToggleButton;
3770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Mollimport com.android.sdkuilib.repository.AvdManagerWindow.AvdInvocationContext;
3870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Mollimport com.android.sdkuilib.repository.ISdkChangeListener;
3970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Mollimport com.android.sdkuilib.repository.SdkUpdaterWindow.SdkInvocationContext;
40ae6a209f6f4030e1ebe20118f9455547e4cd50fcXavier Ducrohetimport com.android.utils.ILogger;
4170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
4270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Mollimport org.eclipse.swt.SWT;
4370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Mollimport org.eclipse.swt.events.DisposeEvent;
4470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Mollimport org.eclipse.swt.events.DisposeListener;
4570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Mollimport org.eclipse.swt.events.SelectionAdapter;
4670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Mollimport org.eclipse.swt.events.SelectionEvent;
4770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Mollimport org.eclipse.swt.graphics.Image;
4870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Mollimport org.eclipse.swt.graphics.Point;
4970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Mollimport org.eclipse.swt.layout.GridData;
5070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Mollimport org.eclipse.swt.layout.GridLayout;
5170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Mollimport org.eclipse.swt.widgets.Composite;
5270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Mollimport org.eclipse.swt.widgets.Display;
5370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Mollimport org.eclipse.swt.widgets.Event;
5470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Mollimport org.eclipse.swt.widgets.Label;
5570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Mollimport org.eclipse.swt.widgets.Listener;
5670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Mollimport org.eclipse.swt.widgets.Menu;
5770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Mollimport org.eclipse.swt.widgets.MenuItem;
5870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Mollimport org.eclipse.swt.widgets.ProgressBar;
5970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Mollimport org.eclipse.swt.widgets.Shell;
6070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
6170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll/**
6270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll * This is the private implementation of the UpdateWindow
6370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll * for the second version of the SDK Manager.
6470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll * <p/>
6570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll * This window features only one embedded page, the combined installed+available package list.
6670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll */
6770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Mollpublic class SdkUpdaterWindowImpl2 implements ISdkUpdaterWindow {
6870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
6970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    public static final String APP_NAME = "Android SDK Manager";
7070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    private static final String SIZE_POS_PREFIX = "sdkman2"; //$NON-NLS-1$
7170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
7270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    private final Shell mParentShell;
7370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    private final SdkInvocationContext mContext;
7470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    /** Internal data shared between the window and its pages. */
7570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    private final UpdaterData mUpdaterData;
7670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
7770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    // --- UI members ---
7870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
7970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    protected Shell mShell;
8070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    private PackagesPage mPkgPage;
8170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    private ProgressBar mProgressBar;
8270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    private Label mStatusText;
8370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    private ImgDisabledButton mButtonStop;
8470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    private ToggleButton mButtonShowLog;
8570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    private SettingsController mSettingsController;
8670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    private LogWindow mLogWindow;
8770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
8870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    /**
8970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     * Creates a new window. Caller must call open(), which will block.
9070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     *
9170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     * @param parentShell Parent shell.
9270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     * @param sdkLog Logger. Cannot be null.
9370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     * @param osSdkRoot The OS path to the SDK root.
9470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     * @param context The {@link SdkInvocationContext} to change the behavior depending on who's
9570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     *  opening the SDK Manager.
9670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     */
9770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    public SdkUpdaterWindowImpl2(
9870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            Shell parentShell,
99ae6a209f6f4030e1ebe20118f9455547e4cd50fcXavier Ducrohet            ILogger sdkLog,
10070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            String osSdkRoot,
10170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            SdkInvocationContext context) {
10270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mParentShell = parentShell;
10370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mContext = context;
10470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mUpdaterData = new UpdaterData(osSdkRoot, sdkLog);
10570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    }
10670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
10770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    /**
10870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     * Creates a new window. Caller must call open(), which will block.
10970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     * <p/>
11070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     * This is to be used when the window is opened from {@link AvdManagerWindowImpl1}
11170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     * to share the same {@link UpdaterData} structure.
11270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     *
11370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     * @param parentShell Parent shell.
11470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     * @param updaterData The parent's updater data.
11570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     * @param context The {@link SdkInvocationContext} to change the behavior depending on who's
11670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     *  opening the SDK Manager.
11770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     */
11870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    public SdkUpdaterWindowImpl2(
11970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            Shell parentShell,
12070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            UpdaterData updaterData,
12170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            SdkInvocationContext context) {
12270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mParentShell = parentShell;
12370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mContext = context;
12470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mUpdaterData = updaterData;
12570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    }
12670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
12770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    /**
12870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     * Opens the window.
12970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     * @wbp.parser.entryPoint
13070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     */
13170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    @Override
13270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    public void open() {
13370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        if (mParentShell == null) {
13470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            Display.setAppName(APP_NAME); //$hide$ (hide from SWT designer)
13570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        }
13670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
13770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        createShell();
13870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        preCreateContent();
13970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        createContents();
14070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        createMenuBar();
14170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        createLogWindow();
14270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mShell.open();
14370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mShell.layout();
14470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
14570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        if (postCreateContent()) {    //$hide$ (hide from SWT designer)
14670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            Display display = Display.getDefault();
14770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            while (!mShell.isDisposed()) {
14870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                if (!display.readAndDispatch()) {
14970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                    display.sleep();
15070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                }
15170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            }
15270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        }
15370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
15470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        SdkSourceProperties p = new SdkSourceProperties();
15570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        p.save();
15670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
15770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        dispose();  //$hide$
15870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    }
15970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
16070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    private void createShell() {
16170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        // The SDK Manager must use a shell trim when standalone
16270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        // or a dialog trim when invoked from somewhere else.
16370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        int style = SWT.SHELL_TRIM;
16470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        if (mContext != SdkInvocationContext.STANDALONE) {
16570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            style |= SWT.APPLICATION_MODAL;
16670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        }
16770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
16870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mShell = new Shell(mParentShell, style);
16970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mShell.addDisposeListener(new DisposeListener() {
17070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            @Override
17170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            public void widgetDisposed(DisposeEvent e) {
17270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                ShellSizeAndPos.saveSizeAndPos(mShell, SIZE_POS_PREFIX);
17370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                onAndroidSdkUpdaterDispose();    //$hide$ (hide from SWT designer)
17470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            }
17570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        });
17670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
17770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        GridLayout glShell = new GridLayout(2, false);
17870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        glShell.verticalSpacing = 0;
17970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        glShell.horizontalSpacing = 0;
18070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        glShell.marginWidth = 0;
18170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        glShell.marginHeight = 0;
18270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mShell.setLayout(glShell);
18370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
18470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mShell.setMinimumSize(new Point(500, 300));
18570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mShell.setSize(700, 500);
18670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mShell.setText(APP_NAME);
18770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
18870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        ShellSizeAndPos.loadSizeAndPos(mShell, SIZE_POS_PREFIX);
18970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    }
19070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
19170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    private void createContents() {
19270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mPkgPage = new PackagesPage(mShell, SWT.NONE, mUpdaterData, mContext);
19370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mPkgPage.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
19470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
19570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        Composite composite1 = new Composite(mShell, SWT.NONE);
19670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        composite1.setLayout(new GridLayout(1, false));
19770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        composite1.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
19870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
19970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mProgressBar = new ProgressBar(composite1, SWT.NONE);
20070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mProgressBar.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
20170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
20270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mStatusText = new Label(composite1, SWT.NONE);
20370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mStatusText.setText("Status Placeholder");  //$NON-NLS-1$ placeholder
20470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mStatusText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
20570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
20670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        Composite composite2 = new Composite(mShell, SWT.NONE);
20770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        composite2.setLayout(new GridLayout(2, false));
20870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
20970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mButtonStop = new ImgDisabledButton(composite2, SWT.NONE,
21070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                getImage("stop_enabled_16.png"),    //$NON-NLS-1$
21170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                getImage("stop_disabled_16.png"),   //$NON-NLS-1$
21270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                "Click to abort the current task",
21370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                "");                                //$NON-NLS-1$ nothing to abort
21470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mButtonStop.addListener(SWT.Selection, new Listener() {
21570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            @Override
21670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            public void handleEvent(Event event) {
21770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                onStopSelected();
21870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            }
21970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        });
22070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
22170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mButtonShowLog = new ToggleButton(composite2, SWT.NONE,
22270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                getImage("log_off_16.png"),         //$NON-NLS-1$
22370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                getImage("log_on_16.png"),          //$NON-NLS-1$
22470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                "Click to show the log window",     // tooltip for state hidden=>shown
22570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                "Click to hide the log window");    // tooltip for state shown=>hidden
22670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mButtonShowLog.addListener(SWT.Selection, new Listener() {
22770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            @Override
22870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            public void handleEvent(Event event) {
22970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                onToggleLogWindow();
23070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            }
23170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        });
23270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    }
23370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
23470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    @SuppressWarnings("unused") // MenuItem works using side effects
23570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    private void createMenuBar() {
23670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
23770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        Menu menuBar = new Menu(mShell, SWT.BAR);
23870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mShell.setMenuBar(menuBar);
23970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
24070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        MenuItem menuBarPackages = new MenuItem(menuBar, SWT.CASCADE);
24170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        menuBarPackages.setText("Packages");
24270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
24370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        Menu menuPkgs = new Menu(menuBarPackages);
24470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        menuBarPackages.setMenu(menuPkgs);
24570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
24670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        MenuItem showUpdatesNew = new MenuItem(menuPkgs,
24770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                MenuAction.TOGGLE_SHOW_UPDATE_NEW_PKG.getMenuStyle());
24870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        showUpdatesNew.setText(
24970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                MenuAction.TOGGLE_SHOW_UPDATE_NEW_PKG.getMenuTitle());
25070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mPkgPage.registerMenuAction(
25170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                MenuAction.TOGGLE_SHOW_UPDATE_NEW_PKG, showUpdatesNew);
25270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
25370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        MenuItem showInstalled = new MenuItem(menuPkgs,
25470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                MenuAction.TOGGLE_SHOW_INSTALLED_PKG.getMenuStyle());
25570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        showInstalled.setText(
25670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                MenuAction.TOGGLE_SHOW_INSTALLED_PKG.getMenuTitle());
25770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mPkgPage.registerMenuAction(
25870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                MenuAction.TOGGLE_SHOW_INSTALLED_PKG, showInstalled);
25970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
26070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        MenuItem showObsoletePackages = new MenuItem(menuPkgs,
26170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                MenuAction.TOGGLE_SHOW_OBSOLETE_PKG.getMenuStyle());
26270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        showObsoletePackages.setText(
26370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                MenuAction.TOGGLE_SHOW_OBSOLETE_PKG.getMenuTitle());
26470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mPkgPage.registerMenuAction(
26570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                MenuAction.TOGGLE_SHOW_OBSOLETE_PKG, showObsoletePackages);
26670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
26770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        MenuItem showArchives = new MenuItem(menuPkgs,
26870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                MenuAction.TOGGLE_SHOW_ARCHIVES.getMenuStyle());
26970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        showArchives.setText(
27070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                MenuAction.TOGGLE_SHOW_ARCHIVES.getMenuTitle());
27170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mPkgPage.registerMenuAction(
27270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                MenuAction.TOGGLE_SHOW_ARCHIVES, showArchives);
27370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
27470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        new MenuItem(menuPkgs, SWT.SEPARATOR);
27570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
27670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        MenuItem sortByApi = new MenuItem(menuPkgs,
27770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                MenuAction.SORT_API_LEVEL.getMenuStyle());
27870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        sortByApi.setText(
27970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                MenuAction.SORT_API_LEVEL.getMenuTitle());
28070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mPkgPage.registerMenuAction(
28170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                MenuAction.SORT_API_LEVEL, sortByApi);
28270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
28370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        MenuItem sortBySource = new MenuItem(menuPkgs,
28470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                MenuAction.SORT_SOURCE.getMenuStyle());
28570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        sortBySource.setText(
28670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                MenuAction.SORT_SOURCE.getMenuTitle());
28770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mPkgPage.registerMenuAction(
28870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                MenuAction.SORT_SOURCE, sortBySource);
28970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
29070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        new MenuItem(menuPkgs, SWT.SEPARATOR);
29170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
29270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        MenuItem reload = new MenuItem(menuPkgs,
29370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                MenuAction.RELOAD.getMenuStyle());
29470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        reload.setText(
29570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                MenuAction.RELOAD.getMenuTitle());
29670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mPkgPage.registerMenuAction(
29770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                MenuAction.RELOAD, reload);
29870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
29970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        MenuItem menuBarTools = new MenuItem(menuBar, SWT.CASCADE);
30070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        menuBarTools.setText("Tools");
30170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
30270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        Menu menuTools = new Menu(menuBarTools);
30370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        menuBarTools.setMenu(menuTools);
30470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
30570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        if (mContext == SdkInvocationContext.STANDALONE) {
30670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            MenuItem manageAvds = new MenuItem(menuTools, SWT.NONE);
30770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            manageAvds.setText("Manage AVDs...");
30870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            manageAvds.addSelectionListener(new SelectionAdapter() {
30970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                @Override
31070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                public void widgetSelected(SelectionEvent event) {
31170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                    onAvdManager();
31270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                }
31370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            });
31470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        }
31570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
31670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        MenuItem manageSources = new MenuItem(menuTools,
31770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                MenuAction.SHOW_ADDON_SITES.getMenuStyle());
31870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        manageSources.setText(
31970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                MenuAction.SHOW_ADDON_SITES.getMenuTitle());
32070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mPkgPage.registerMenuAction(
32170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                MenuAction.SHOW_ADDON_SITES, manageSources);
32270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
32370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        if (mContext == SdkInvocationContext.STANDALONE || mContext == SdkInvocationContext.IDE) {
32470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            try {
32570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                new MenuBarWrapper(APP_NAME, menuTools) {
32670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                    @Override
32770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                    public void onPreferencesMenuSelected() {
32870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
32970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                        // capture a copy of the initial settings
33070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                        Settings settings1 = new Settings(mSettingsController.getSettings());
33170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
33270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                        // open the dialog and wait for it to close
33370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                        SettingsDialog sd = new SettingsDialog(mShell, mUpdaterData);
33470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                        sd.open();
33570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
33670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                        // get the new settings
33770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                        Settings settings2 = mSettingsController.getSettings();
33870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
33970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                        // We need to reload the package list if the http mode or the preview
34070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                        // modes have changed.
34170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                        if (settings1.getForceHttp() != settings2.getForceHttp() ||
34270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                                settings1.getEnablePreviews() != settings2.getEnablePreviews()) {
34370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                            mPkgPage.onSdkReload();
34470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                        }
34570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                    }
34670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
34770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                    @Override
34870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                    public void onAboutMenuSelected() {
34970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                        AboutDialog ad = new AboutDialog(mShell, mUpdaterData);
35070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                        ad.open();
35170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                    }
35270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
35370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                    @Override
35470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                    public void printError(String format, Object... args) {
35570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                        if (mUpdaterData != null) {
35670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                            mUpdaterData.getSdkLog().error(null, format, args);
35770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                        }
35870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                    }
35970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                };
36070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            } catch (Throwable e) {
36170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                mUpdaterData.getSdkLog().error(e, "Failed to setup menu bar");
36270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                e.printStackTrace();
36370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            }
36470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        }
36570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    }
36670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
36770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    private Image getImage(String filename) {
36870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        if (mUpdaterData != null) {
36970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            ImageFactory imgFactory = mUpdaterData.getImageFactory();
37070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            if (imgFactory != null) {
37170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                return imgFactory.getImageByName(filename);
37270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            }
37370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        }
37470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        return null;
37570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    }
37670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
37770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    /**
37870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     * Creates the log window.
37970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     * <p/>
38070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     * If this is invoked from an IDE, we also define a secondary logger so that all
38170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     * messages flow to the IDE log. This may or may not be what we want in the end
38270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     * (e.g. a middle ground would be to repeat error, and ignore normal/verbose)
38370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     */
38470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    private void createLogWindow() {
38570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mLogWindow = new LogWindow(mShell,
38670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                mContext == SdkInvocationContext.IDE ? mUpdaterData.getSdkLog() : null);
38770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mLogWindow.open();
38870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    }
38970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
39070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
39170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    // -- Start of internal part ----------
39270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    // Hide everything down-below from SWT designer
39370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    //$hide>>$
39470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
39570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    // --- Public API -----------
39670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
39770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    /**
39870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     * Adds a new listener to be notified when a change is made to the content of the SDK.
39970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     */
40070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    @Override
40170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    public void addListener(ISdkChangeListener listener) {
40270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mUpdaterData.addListeners(listener);
40370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    }
40470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
40570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    /**
40670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     * Removes a new listener to be notified anymore when a change is made to the content of
40770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     * the SDK.
40870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     */
40970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    @Override
41070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    public void removeListener(ISdkChangeListener listener) {
41170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mUpdaterData.removeListener(listener);
41270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    }
41370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
41470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    // --- Internals & UI Callbacks -----------
41570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
41670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    /**
41770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     * Called before the UI is created.
41870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     */
41970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    private void preCreateContent() {
42070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mUpdaterData.setWindowShell(mShell);
42170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        // We need the UI factory to create the UI
42270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mUpdaterData.setImageFactory(new ImageFactory(mShell.getDisplay()));
42370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        // Note: we can't create the TaskFactory yet because we need the UI
42470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        // to be created first, so this is done in postCreateContent().
42570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    }
42670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
42770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    /**
42870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     * Once the UI has been created, initializes the content.
42970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     * This creates the pages, selects the first one, setups sources and scans for local folders.
43070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     *
43170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     * Returns true if we should show the window.
43270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     */
43370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    private boolean postCreateContent() {
43470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        ProgressViewFactory factory = new ProgressViewFactory();
43570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
43670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        // This class delegates all logging to the mLogWindow window
43770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        // and filters errors to make sure the window is visible when
43870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        // an error is logged.
43970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        ILogUiProvider logAdapter = new ILogUiProvider() {
44070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            @Override
44170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            public void setDescription(String description) {
44270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                mLogWindow.setDescription(description);
44370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            }
44470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
44570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            @Override
44670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            public void log(String log) {
44770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                mLogWindow.log(log);
44870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            }
44970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
45070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            @Override
45170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            public void logVerbose(String log) {
45270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                mLogWindow.logVerbose(log);
45370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            }
45470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
45570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            @Override
45670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            public void logError(String log) {
45770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                mLogWindow.logError(log);
45870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
45970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                // Run the window visibility check/toggle on the UI thread.
46070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                // Note: at least on Windows, it seems ok to check for the window visibility
46170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                // on a sub-thread but that doesn't seem cross-platform safe. We shouldn't
46270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                // have a lot of error logging, so this should be acceptable. If not, we could
46370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                // cache the visibility state.
46470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                if (mShell != null && !mShell.isDisposed()) {
46570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                    mShell.getDisplay().syncExec(new Runnable() {
46670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                        @Override
46770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                        public void run() {
46870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                            if (!mLogWindow.isVisible()) {
46970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                                // Don't toggle the window visibility directly.
47070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                                // Instead use the same action as the log-toggle button
47170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                                // so that the button's state be kept in sync.
47270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                                onToggleLogWindow();
47370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                            }
47470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                        }
47570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                    });
47670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                }
47770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            }
47870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        };
47970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
48070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        factory.setProgressView(
48170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                new ProgressView(mStatusText, mProgressBar, mButtonStop, logAdapter));
48270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mUpdaterData.setTaskFactory(factory);
48370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
48470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        setWindowImage(mShell);
48570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
48670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        setupSources();
48770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        initializeSettings();
48870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
48970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        if (mUpdaterData.checkIfInitFailed()) {
49070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            return false;
49170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        }
49270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
49370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mUpdaterData.broadcastOnSdkLoaded();
49470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
49570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        // Tell the one page its the selected one
49670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mPkgPage.performFirstLoad();
49770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
49870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        return true;
49970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    }
50070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
50170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    /**
50270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     * Creates the icon of the window shell.
50370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     *
50470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     * @param shell The shell on which to put the icon
50570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     */
50670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    private void setWindowImage(Shell shell) {
50770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        String imageName = "android_icon_16.png"; //$NON-NLS-1$
50870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        if (SdkConstants.currentPlatform() == SdkConstants.PLATFORM_DARWIN) {
50970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            imageName = "android_icon_128.png"; //$NON-NLS-1$
51070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        }
51170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
51270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        if (mUpdaterData != null) {
51370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            ImageFactory imgFactory = mUpdaterData.getImageFactory();
51470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            if (imgFactory != null) {
51570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                shell.setImage(imgFactory.getImageByName(imageName));
51670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            }
51770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        }
51870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    }
51970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
52070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    /**
52170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     * Called by the main loop when the window has been disposed.
52270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     */
52370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    private void dispose() {
52470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mLogWindow.close();
52570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mUpdaterData.getSources().saveUserAddons(mUpdaterData.getSdkLog());
52670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    }
52770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
52870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    /**
52970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     * Callback called when the window shell is disposed.
53070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     */
53170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    private void onAndroidSdkUpdaterDispose() {
53270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        if (mUpdaterData != null) {
53370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            ImageFactory imgFactory = mUpdaterData.getImageFactory();
53470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            if (imgFactory != null) {
53570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                imgFactory.dispose();
53670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            }
53770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        }
53870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    }
53970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
54070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    /**
54170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     * Used to initialize the sources.
54270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     */
54370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    private void setupSources() {
54470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mUpdaterData.setupDefaultSources();
54570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    }
54670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
54770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    /**
54870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     * Initializes settings.
54970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     * This must be called after addExtraPages(), which created a settings page.
55070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     * Iterate through all the pages to find the first (and supposedly unique) setting page,
55170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     * and use it to load and apply these settings.
55270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll     */
55370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    private void initializeSettings() {
55470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mSettingsController = mUpdaterData.getSettingsController();
55570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mSettingsController.loadSettings();
55670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        mSettingsController.applySettings();
55770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    }
55870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
55970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    private void onToggleLogWindow() {
56070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        // toggle visibility
56170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        if (!mButtonShowLog.isDisposed()) {
56270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            mLogWindow.setVisible(!mLogWindow.isVisible());
56370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            mButtonShowLog.setState(mLogWindow.isVisible() ? 1 : 0);
56470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        }
56570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    }
56670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
56770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    private void onStopSelected() {
56870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        // TODO
56970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    }
57070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
57170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    private void onAvdManager() {
57270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        ITaskFactory oldFactory = mUpdaterData.getTaskFactory();
57370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
57470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        try {
57570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            AvdManagerWindowImpl1 win = new AvdManagerWindowImpl1(
57670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                    mShell,
57770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                    mUpdaterData,
57870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll                    AvdInvocationContext.DIALOG);
57970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
58070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            win.open();
58170c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        } catch (Exception e) {
58270c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            mUpdaterData.getSdkLog().error(e, "AVD Manager window error");
58370c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        } finally {
58470c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll            mUpdaterData.setTaskFactory(oldFactory);
58570c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll        }
58670c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    }
58770c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll
58870c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    // End of hiding from SWT Designer
58970c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll    //$hide<<$
59070c222d49c0a75e30b05337dbbb8110a39635aafRaphael Moll}
591