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.avd.HardwareProperties.HardwareProperty;
import com.android.sdklib.internal.project.ProjectCreator; import com.android.sdklib.internal.project.ProjectCreator;
import com.android.sdklib.internal.project.ProjectCreator.OutputLevel; 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 com.android.sdkuilib.repository.UpdaterWindow;
import java.io.File; import java.io.File;
@@ -238,8 +240,11 @@ class Main {
private void showMainWindow() { private void showMainWindow() {
try { try {
UpdaterWindow window = new UpdaterWindow( UpdaterWindow window = new UpdaterWindow(
mSdkLog,
mOsSdkFolder, mOsSdkFolder,
false /*userCanChangeSdkRoot*/); false /*userCanChangeSdkRoot*/);
window.registerPage("Settings", SettingsPage.class);
window.registerPage("About", AboutPage.class);
window.open(); window.open();
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); 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; 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.ITask;
import com.android.sdklib.internal.repository.ITaskMonitor; 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.jface.viewers.TableViewer;
import org.eclipse.swt.SWT; import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlAdapter; import org.eclipse.swt.events.ControlAdapter;
@@ -38,8 +41,6 @@ import org.eclipse.swt.widgets.Text;
/* /*
* TODO list * TODO list
* - parse local repo
* - create entries
* - select => update desc, enable update + delete, enable home page if url * - select => update desc, enable update + delete, enable home page if url
* - home page callback * - home page callback
* - update callback * - update callback
@@ -89,6 +90,12 @@ public class LocalPackagesPage extends Composite {
mTablePackages = mTableViewerPackages.getTable(); mTablePackages = mTableViewerPackages.getTable();
mTablePackages.setHeaderVisible(true); mTablePackages.setHeaderVisible(true);
mTablePackages.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1)); 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 = new TableColumn(mTablePackages, SWT.NONE);
mColumnPackages.setWidth(377); mColumnPackages.setWidth(377);
@@ -164,11 +171,23 @@ public class LocalPackagesPage extends Composite {
// Hide everything down-below from SWT designer // Hide everything down-below from SWT designer
//$hide>>$ //$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() { private void postCreate() {
adjustColumnsWidth(); adjustColumnsWidth();
} }
/** /**
* Adds a listener to adjust the columns width when the parent is resized. * Adds a listener to adjust the columns width when the parent is resized.
* <p/> * <p/>
@@ -186,13 +205,26 @@ public class LocalPackagesPage extends Composite {
}); });
} }
public void setInput(LocalSdkAdapter localSdkAdapter) { /**
mTableViewerPackages.setLabelProvider( localSdkAdapter.getLabelProvider()); * Called when an item in the package table viewer is selected.
mTableViewerPackages.setContentProvider(localSdkAdapter.getContentProvider()); * If the items is an {@link IDescription} (as it should), this will display its long
mTableViewerPackages.setInput(localSdkAdapter); * 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. // TODO just a test, needs to be removed later.
ProgressTask.start(getShell(), "Test", new ITask() { ProgressTask.start(getShell(), "Test", new ITask() {
public void run(ITaskMonitor monitor) { public void run(ITaskMonitor monitor) {

View File

@@ -16,6 +16,7 @@
package com.android.sdkuilib.internal.repository; package com.android.sdkuilib.internal.repository;
import com.android.sdklib.ISdkLog;
import com.android.sdklib.internal.repository.LocalSdkParser; import com.android.sdklib.internal.repository.LocalSdkParser;
import com.android.sdklib.internal.repository.RepoSources; 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. * Data shared between {@link UpdaterWindowImpl} and its pages.
*/ */
class UpdaterData { class UpdaterData {
private ISdkLog mSdkLog;
private String mOsSdkRoot; private String mOsSdkRoot;
private boolean mUserCanChangeSdkRoot; private boolean mUserCanChangeSdkRoot;
@@ -64,4 +66,11 @@ class UpdaterData {
return mLocalSdkAdapter; 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; package com.android.sdkuilib.internal.repository;
import com.android.sdklib.ISdkLog;
import com.android.sdklib.internal.repository.Archive; import com.android.sdklib.internal.repository.Archive;
import com.android.sdklib.internal.repository.ITask; import com.android.sdklib.internal.repository.ITask;
import com.android.sdklib.internal.repository.ITaskMonitor; import com.android.sdklib.internal.repository.ITaskMonitor;
@@ -45,6 +46,7 @@ import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.net.URL; import java.net.URL;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.util.ArrayList; import java.util.ArrayList;
@@ -57,9 +59,18 @@ public class UpdaterWindowImpl {
private static final int NUM_FETCH_URL_MONITOR_INC = 10; 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(); 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>(); private ArrayList<Composite> mPages = new ArrayList<Composite>();
/** Indicates a page change is due to an internal request. Prevents callbacks from looping. */
private boolean mInternalPageChange; 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 --- // --- UI members ---
@@ -71,9 +82,9 @@ public class UpdaterWindowImpl {
private RemotePackagesPage mRemotePackagesPage; private RemotePackagesPage mRemotePackagesPage;
private StackLayout mStackLayout; private StackLayout mStackLayout;
private Image mIconImage; 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.setOsSdkRoot(osSdkRoot);
mUpdaterData.setUserCanChangeSdkRoot(userCanChangeSdkRoot); mUpdaterData.setUserCanChangeSdkRoot(userCanChangeSdkRoot);
} }
@@ -140,6 +151,35 @@ public class UpdaterWindowImpl {
// --- UI Callbacks ----------- // --- 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() { private void onAndroidSdkUpdaterDispose() {
if (mIconImage != null) { if (mIconImage != null) {
mIconImage.dispose(); 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) { private void setWindowImage(Shell androidSdkUpdater) {
InputStream stream = getClass().getResourceAsStream("android_icon_16.png"); //$NON-NLS-1$ InputStream stream = getClass().getResourceAsStream("android_icon_16.png"); //$NON-NLS-1$
if (stream != null) { if (stream != null) {
@@ -157,40 +201,84 @@ public class UpdaterWindowImpl {
imgData.getTransparencyMask()); imgData.getTransparencyMask());
mAndroidSdkUpdater.setImage(mIconImage); mAndroidSdkUpdater.setImage(mIconImage);
} catch (SWTException e) { } catch (SWTException e) {
// ignore mUpdaterData.getSdkLog().error(e, "Failed to set window icon"); //$NON-NLS-1$
} catch (IllegalArgumentException e) { } 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() { private void firstInit() {
mTaskFactory = new ProgressTaskFactory(getShell()); mTaskFactory = new ProgressTaskFactory(getShell());
addPage(mLocalPackagePage, "Installed Packages"); addPage(mLocalPackagePage, "Installed Packages");
addPage(mRemotePackagesPage, "Available Packages"); addPage(mRemotePackagesPage, "Available Packages");
addExtraPages();
displayPage(0); displayPage(0);
mPageList.setSelection(0); mPageList.setSelection(0);
// TODO read and apply settings
// TODO read add-on sources from some file
setupSources(); setupSources();
scanLocalSdkFolders(); scanLocalSdkFolders();
} }
// --- page switching --- // --- 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) { private void addPage(Composite page, String title) {
page.setData(title); page.setData(title);
mPages.add(page); mPages.add(page);
mPageList.add(title); 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() { private void onPageListSelected() {
if (mInternalPageChange == false) { if (mInternalPageChange == false) {
int index = mPageList.getSelectionIndex(); 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) { private void displayPage(int index) {
Composite page = mPages.get(index); Composite page = mPages.get(index);
if (page != null) { if (page != null) {
@@ -214,6 +307,9 @@ public class UpdaterWindowImpl {
} }
} }
/**
* Used to initialize the sources.
*/
private void setupSources() { private void setupSources() {
mUpdaterData.getSources().setTaskFactory(mTaskFactory); mUpdaterData.getSources().setTaskFactory(mTaskFactory);
@@ -228,12 +324,19 @@ public class UpdaterWindowImpl {
mRemotePackagesPage.setInput(mUpdaterData.getSourcesAdapter()); mRemotePackagesPage.setInput(mUpdaterData.getSourcesAdapter());
} }
/**
* Used to scan the local SDK folders the first time.
*/
private void scanLocalSdkFolders() { private void scanLocalSdkFolders() {
mUpdaterData.getLocalSdkAdapter().setSdkRoot(mUpdaterData.getOsSdkRoot()); mUpdaterData.getLocalSdkAdapter().setSdkRoot(mUpdaterData.getOsSdkRoot());
mLocalPackagePage.setInput(mUpdaterData.getLocalSdkAdapter()); 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) { public void installArchives(final Collection<Archive> archives) {
// TODO move most parts to SdkLib, maybe as part of Archive, making archives self-installing. // TODO move most parts to SdkLib, maybe as part of Archive, making archives self-installing.
mTaskFactory.start("Installing Archives", new ITask() { mTaskFactory.start("Installing Archives", new ITask() {

View File

@@ -16,8 +16,11 @@
package com.android.sdkuilib.repository; package com.android.sdkuilib.repository;
import com.android.sdklib.ISdkLog;
import com.android.sdkuilib.internal.repository.UpdaterWindowImpl; import com.android.sdkuilib.internal.repository.UpdaterWindowImpl;
import org.eclipse.swt.widgets.Composite;
/** /**
* Opens an SDK Updater Window. * Opens an SDK Updater Window.
* *
@@ -29,12 +32,28 @@ public class UpdaterWindow {
/** /**
* Creates a new window. Caller must call open(), which will block. * Creates a new window. Caller must call open(), which will block.
* @param sdkLog
* @param osSdkRoot The OS path to the SDK root. * @param osSdkRoot The OS path to the SDK root.
* @param userCanChangeSdkRoot If true, the window lets the user change the SDK path * @param userCanChangeSdkRoot If true, the window lets the user change the SDK path
* being browsed. * being browsed.
*/ */
public UpdaterWindow(String osSdkRoot, boolean userCanChangeSdkRoot) { public UpdaterWindow(ISdkLog sdkLog, String osSdkRoot, boolean userCanChangeSdkRoot) {
mWindow = new UpdaterWindowImpl(osSdkRoot, 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);
} }
/** /**