SDK Updater: Placeholder pages for about and settings.

These pages are now in the SdkManager project
with a mechanism to instantiate them from the UI on demand.
This commit is contained in:
Raphael
2009-06-01 15:45:33 -07:00
parent 55b47f8d75
commit 36e11cb354
7 changed files with 368 additions and 19 deletions

View File

@@ -29,6 +29,8 @@ import com.android.sdklib.internal.avd.AvdManager.AvdInfo;
import com.android.sdklib.internal.avd.HardwareProperties.HardwareProperty;
import com.android.sdklib.internal.project.ProjectCreator;
import com.android.sdklib.internal.project.ProjectCreator.OutputLevel;
import com.android.sdkmanager.internal.repository.AboutPage;
import com.android.sdkmanager.internal.repository.SettingsPage;
import com.android.sdkuilib.repository.UpdaterWindow;
import java.io.File;
@@ -238,8 +240,11 @@ class Main {
private void showMainWindow() {
try {
UpdaterWindow window = new UpdaterWindow(
mSdkLog,
mOsSdkFolder,
false /*userCanChangeSdkRoot*/);
window.registerPage("Settings", SettingsPage.class);
window.registerPage("About", AboutPage.class);
window.open();
} catch (Exception e) {
e.printStackTrace();

View File

@@ -0,0 +1,72 @@
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.sdkmanager.internal.repository;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
/*
* TODO list
* - Change version to be a constant pulled from somewhere.
*/
public class AboutPage extends Composite {
private Label mLabel;
/**
* Create the composite.
* @param parent The parent of the composite.
*/
public AboutPage(Composite parent) {
super(parent, SWT.BORDER);
createContents(this);
postCreate(); //$hide$
}
private void createContents(Composite parent) {
parent.setLayout(new GridLayout(1, false));
mLabel = new Label(parent, SWT.NONE);
mLabel.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, true, 1, 1));
mLabel.setText("Android SDK Updater.\n\nVersion 0.1.\n\nCopyright (C) 2009 The Android Open Source Project.");
}
@Override
protected void checkSubclass() {
// Disable the check that prevents subclassing of SWT components
}
// -- Start of internal part ----------
// Hide everything down-below from SWT designer
//$hide>>$
/**
* Called by the constructor right after {@link #createContents(Composite)}.
*/
private void postCreate() {
}
// End of hiding from SWT Designer
//$hide<<$
}

View File

@@ -0,0 +1,109 @@
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.sdkmanager.internal.repository;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
/*
* TODO list
* - The window should probably set a callback to be notified when settings are changed.
* - Actually use the settings.
*/
public class SettingsPage extends Composite {
private Group mProxySettingsGroup;
private Group mPlaceholderGroup;
private Button mApplyButton;
private Label mSomeMoreSettings;
private Label mProxyServerLabel;
private Label mProxyPortLabel;
private Text mProxyServerText;
private Text mProxyPortText;
/**
* Create the composite.
* @param parent The parent of the composite.
*/
public SettingsPage(Composite parent) {
super(parent, SWT.BORDER);
createContents(this);
mProxySettingsGroup = new Group(this, SWT.NONE);
mProxySettingsGroup.setText("Proxy Settings");
mProxySettingsGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
mProxySettingsGroup.setLayout(new GridLayout(2, false));
mProxyServerLabel = new Label(mProxySettingsGroup, SWT.NONE);
mProxyServerLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
mProxyServerLabel.setText("HTTP Proxy Server");
mProxyServerText = new Text(mProxySettingsGroup, SWT.BORDER);
mProxyServerText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
mProxyPortLabel = new Label(mProxySettingsGroup, SWT.NONE);
mProxyPortLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
mProxyPortLabel.setText("HTTP Proxy Port");
mProxyPortText = new Text(mProxySettingsGroup, SWT.BORDER);
mProxyPortText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
mPlaceholderGroup = new Group(this, SWT.NONE);
mPlaceholderGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
mPlaceholderGroup.setText("Placeholder");
mPlaceholderGroup.setLayout(new GridLayout(1, false));
mSomeMoreSettings = new Label(mPlaceholderGroup, SWT.NONE);
mSomeMoreSettings.setText("Some more settings here");
mApplyButton = new Button(this, SWT.NONE);
mApplyButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
mApplyButton.setText("Apply");
postCreate(); //$hide$
}
private void createContents(Composite parent) {
parent.setLayout(new GridLayout(1, false));
}
@Override
protected void checkSubclass() {
// Disable the check that prevents subclassing of SWT components
}
// -- Start of internal part ----------
// Hide everything down-below from SWT designer
//$hide>>$
/**
* Called by the constructor right after {@link #createContents(Composite)}.
*/
private void postCreate() {
}
// End of hiding from SWT Designer
//$hide<<$
}

View File

@@ -16,9 +16,12 @@
package com.android.sdkuilib.internal.repository;
import com.android.sdklib.internal.repository.IDescription;
import com.android.sdklib.internal.repository.ITask;
import com.android.sdklib.internal.repository.ITaskMonitor;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlAdapter;
@@ -38,8 +41,6 @@ import org.eclipse.swt.widgets.Text;
/*
* TODO list
* - parse local repo
* - create entries
* - select => update desc, enable update + delete, enable home page if url
* - home page callback
* - update callback
@@ -89,6 +90,12 @@ public class LocalPackagesPage extends Composite {
mTablePackages = mTableViewerPackages.getTable();
mTablePackages.setHeaderVisible(true);
mTablePackages.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1));
mTablePackages.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
onTreeSelected(); //$hide$
}
});
mColumnPackages = new TableColumn(mTablePackages, SWT.NONE);
mColumnPackages.setWidth(377);
@@ -164,11 +171,23 @@ public class LocalPackagesPage extends Composite {
// Hide everything down-below from SWT designer
//$hide>>$
/**
* Must be called once to set the adapter input for the package table viewer.
*/
public void setInput(LocalSdkAdapter localSdkAdapter) {
mTableViewerPackages.setLabelProvider( localSdkAdapter.getLabelProvider());
mTableViewerPackages.setContentProvider(localSdkAdapter.getContentProvider());
mTableViewerPackages.setInput(localSdkAdapter);
onTreeSelected();
}
/**
* Called by the constructor right after {@link #createContents(Composite)}.
*/
private void postCreate() {
adjustColumnsWidth();
}
/**
* Adds a listener to adjust the columns width when the parent is resized.
* <p/>
@@ -186,13 +205,26 @@ public class LocalPackagesPage extends Composite {
});
}
public void setInput(LocalSdkAdapter localSdkAdapter) {
mTableViewerPackages.setLabelProvider( localSdkAdapter.getLabelProvider());
mTableViewerPackages.setContentProvider(localSdkAdapter.getContentProvider());
mTableViewerPackages.setInput(localSdkAdapter);
/**
* Called when an item in the package table viewer is selected.
* If the items is an {@link IDescription} (as it should), this will display its long
* description in the description area. Otherwise when the item is not of the expected
* type or there is no selection, it empties the description area.
*/
private void onTreeSelected() {
ISelection sel = mTableViewerPackages.getSelection();
if (sel instanceof IStructuredSelection) {
Object elem = ((IStructuredSelection) sel).getFirstElement();
if (elem instanceof IDescription) {
mDescriptionLabel.setText(((IDescription) elem).getLongDescription());
mDescriptionContainer.layout(true);
return;
}
}
mDescriptionLabel.setText(""); //$NON-NLS1-$
}
protected void onUpdateInstalledPackage() {
private void onUpdateInstalledPackage() {
// TODO just a test, needs to be removed later.
ProgressTask.start(getShell(), "Test", new ITask() {
public void run(ITaskMonitor monitor) {

View File

@@ -16,6 +16,7 @@
package com.android.sdkuilib.internal.repository;
import com.android.sdklib.ISdkLog;
import com.android.sdklib.internal.repository.LocalSdkParser;
import com.android.sdklib.internal.repository.RepoSources;
@@ -23,6 +24,7 @@ import com.android.sdklib.internal.repository.RepoSources;
* Data shared between {@link UpdaterWindowImpl} and its pages.
*/
class UpdaterData {
private ISdkLog mSdkLog;
private String mOsSdkRoot;
private boolean mUserCanChangeSdkRoot;
@@ -64,4 +66,11 @@ class UpdaterData {
return mLocalSdkAdapter;
}
public void setSdkLog(ISdkLog sdkLog) {
mSdkLog = sdkLog;
}
public ISdkLog getSdkLog() {
return mSdkLog;
}
}

View File

@@ -17,6 +17,7 @@
package com.android.sdkuilib.internal.repository;
import com.android.sdklib.ISdkLog;
import com.android.sdklib.internal.repository.Archive;
import com.android.sdklib.internal.repository.ITask;
import com.android.sdklib.internal.repository.ITaskMonitor;
@@ -45,6 +46,7 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.net.URL;
import java.security.MessageDigest;
import java.util.ArrayList;
@@ -57,9 +59,18 @@ public class UpdaterWindowImpl {
private static final int NUM_FETCH_URL_MONITOR_INC = 10;
/** Internal data shared between the window and its pages. */
private final UpdaterData mUpdaterData = new UpdaterData();
/** The array of pages instances. Only one is visible at a time. */
private ArrayList<Composite> mPages = new ArrayList<Composite>();
/** Indicates a page change is due to an internal request. Prevents callbacks from looping. */
private boolean mInternalPageChange;
/** A list of extra pages to instantiate. Each entry is an object array with 2 elements:
* the string title and the Composite class to instantiate to create the page. */
private ArrayList<Object[]> mExtraPages;
/** A factory to create progress task dialogs. */
private ProgressTaskFactory mTaskFactory;
// --- UI members ---
@@ -71,9 +82,9 @@ public class UpdaterWindowImpl {
private RemotePackagesPage mRemotePackagesPage;
private StackLayout mStackLayout;
private Image mIconImage;
private ProgressTaskFactory mTaskFactory;
public UpdaterWindowImpl(String osSdkRoot, boolean userCanChangeSdkRoot) {
public UpdaterWindowImpl(ISdkLog sdkLog, String osSdkRoot, boolean userCanChangeSdkRoot) {
mUpdaterData.setSdkLog(sdkLog);
mUpdaterData.setOsSdkRoot(osSdkRoot);
mUpdaterData.setUserCanChangeSdkRoot(userCanChangeSdkRoot);
}
@@ -140,6 +151,35 @@ public class UpdaterWindowImpl {
// --- UI Callbacks -----------
/**
* Registers an extra page for the updater window.
* <p/>
* Pages must derive from {@link Composite} and implement a constructor that takes
* a single parent {@link Composite} argument.
* <p/>
* All pages must be registered before the call to {@link #open()}.
*
* @param title The title of the page.
* @param pageClass The {@link Composite}-derived class that will implement the page.
*/
public void registerExtraPage(String title, Class<? extends Composite> pageClass) {
if (mExtraPages == null) {
mExtraPages = new ArrayList<Object[]>();
}
mExtraPages.add(new Object[]{ title, pageClass });
}
/**
* Helper to return the SWT shell.
*/
private Shell getShell() {
return mAndroidSdkUpdater;
}
/**
* Callback called when the window shell is disposed.
*/
private void onAndroidSdkUpdaterDispose() {
if (mIconImage != null) {
mIconImage.dispose();
@@ -147,6 +187,10 @@ public class UpdaterWindowImpl {
}
}
/**
* Creates the icon of the window shell.
* The icon is disposed by {@link #onAndroidSdkUpdaterDispose()}.
*/
private void setWindowImage(Shell androidSdkUpdater) {
InputStream stream = getClass().getResourceAsStream("android_icon_16.png"); //$NON-NLS-1$
if (stream != null) {
@@ -157,40 +201,84 @@ public class UpdaterWindowImpl {
imgData.getTransparencyMask());
mAndroidSdkUpdater.setImage(mIconImage);
} catch (SWTException e) {
// ignore
mUpdaterData.getSdkLog().error(e, "Failed to set window icon"); //$NON-NLS-1$
} catch (IllegalArgumentException e) {
// ignore
mUpdaterData.getSdkLog().error(e, "Failed to set window icon"); //$NON-NLS-1$
}
}
}
private Shell getShell() {
return mAndroidSdkUpdater;
}
/**
* Once the UI has been created, initialize the content
* Once the UI has been created, initializes the content.
* This creates the pages, selects the first one, setup sources and scan for local folders.
*/
private void firstInit() {
mTaskFactory = new ProgressTaskFactory(getShell());
addPage(mLocalPackagePage, "Installed Packages");
addPage(mRemotePackagesPage, "Available Packages");
addExtraPages();
displayPage(0);
mPageList.setSelection(0);
// TODO read and apply settings
// TODO read add-on sources from some file
setupSources();
scanLocalSdkFolders();
}
// --- page switching ---
/**
* Adds an instance of a page to the page list.
* <p/>
* Each page is a {@link Composite}. The title of the page is stored in the
* {@link Composite#getData()} field.
*/
private void addPage(Composite page, String title) {
page.setData(title);
mPages.add(page);
mPageList.add(title);
}
/**
* Adds all extra pages. For each page, instantiates an instance of the {@link Composite}
* using the constructor that takes a single {@link Composite} argument and then adds it
* to the page list.
*/
@SuppressWarnings("unchecked")
private void addExtraPages() {
for (Object[] extraPage : mExtraPages) {
String title = (String) extraPage[0];
Class<? extends Composite> clazz = (Class<? extends Composite>) extraPage[1];
// We want the constructor that takes a single Composite as parameter
Constructor<? extends Composite> cons;
try {
cons = clazz.getConstructor(new Class<?>[] { Composite.class });
Composite instance = cons.newInstance(new Object[] { mPagesRootComposite });
addPage(instance, title);
} catch (NoSuchMethodException e) {
// There is no such constructor.
mUpdaterData.getSdkLog().error(e,
"Failed to add extra page %1$s. Constructor args must be (Composite parent).", //$NON-NLS-1$
clazz.getSimpleName());
} catch (Exception e) {
// Log this instead of crashing the whole app.
mUpdaterData.getSdkLog().error(e,
"Failed to add extra page %1$s.", //$NON-NLS-1$
clazz.getSimpleName());
}
}
}
/**
* Callback invoked when an item is selected in the page list.
* If this is not an internal page change, displays the given page.
*/
private void onPageListSelected() {
if (mInternalPageChange == false) {
int index = mPageList.getSelectionIndex();
@@ -200,6 +288,11 @@ public class UpdaterWindowImpl {
}
}
/**
* Displays the page at the given index.
*
* @param index An index between 0 and {@link #mPages}'s length - 1.
*/
private void displayPage(int index) {
Composite page = mPages.get(index);
if (page != null) {
@@ -214,6 +307,9 @@ public class UpdaterWindowImpl {
}
}
/**
* Used to initialize the sources.
*/
private void setupSources() {
mUpdaterData.getSources().setTaskFactory(mTaskFactory);
@@ -228,12 +324,19 @@ public class UpdaterWindowImpl {
mRemotePackagesPage.setInput(mUpdaterData.getSourcesAdapter());
}
/**
* Used to scan the local SDK folders the first time.
*/
private void scanLocalSdkFolders() {
mUpdaterData.getLocalSdkAdapter().setSdkRoot(mUpdaterData.getOsSdkRoot());
mLocalPackagePage.setInput(mUpdaterData.getLocalSdkAdapter());
}
/**
* Install the list of given {@link Archive}s.
* @param archives The archives to install. Incompatible ones will be skipped.
*/
public void installArchives(final Collection<Archive> archives) {
// TODO move most parts to SdkLib, maybe as part of Archive, making archives self-installing.
mTaskFactory.start("Installing Archives", new ITask() {

View File

@@ -16,8 +16,11 @@
package com.android.sdkuilib.repository;
import com.android.sdklib.ISdkLog;
import com.android.sdkuilib.internal.repository.UpdaterWindowImpl;
import org.eclipse.swt.widgets.Composite;
/**
* Opens an SDK Updater Window.
*
@@ -29,12 +32,28 @@ public class UpdaterWindow {
/**
* Creates a new window. Caller must call open(), which will block.
* @param sdkLog
* @param osSdkRoot The OS path to the SDK root.
* @param userCanChangeSdkRoot If true, the window lets the user change the SDK path
* being browsed.
*/
public UpdaterWindow(String osSdkRoot, boolean userCanChangeSdkRoot) {
mWindow = new UpdaterWindowImpl(osSdkRoot, userCanChangeSdkRoot);
public UpdaterWindow(ISdkLog sdkLog, String osSdkRoot, boolean userCanChangeSdkRoot) {
mWindow = new UpdaterWindowImpl(sdkLog, osSdkRoot, userCanChangeSdkRoot);
}
/**
* Registers an extra page for the updater window.
* <p/>
* Pages must derive from {@link Composite} and implement a constructor that takes
* a single parent {@link Composite} argument.
* <p/>
* All pages must be registered before the call to {@link #open()}.
*
* @param title The title of the page.
* @param pageClass The {@link Composite}-derived class that will implement the page.
*/
public void registerPage(String title, Class<? extends Composite> pageClass) {
mWindow.registerExtraPage(title, pageClass);
}
/**