From 08226b31f800e5e7513dc43a32ca6e8ab7ce84bc Mon Sep 17 00:00:00 2001 From: Raphael Date: Tue, 19 May 2009 23:25:54 -0700 Subject: [PATCH] SDK Updater: Fetch source XML, display them in tree. There's a notion of an asynchronous task with a progress bar & status UI. That's still just experimental. Will need some refactoring, etc. --- .../app/src/com/android/sdkmanager/Main.java | 20 +- .../sdklib/repository/SdkRepository.java | 44 +++ .../repository/SdkRepositoryConstants.java | 33 -- .../sdklib/repository/TestSdkRepository.java | 2 +- .../sdkuilib/repository/ITaskMonitor.java | 60 +++ .../sdkuilib/repository/ProgressTask.java | 235 ++++++++++++ .../sdkuilib/repository/RepoSource.java | 316 ++++++++++++++++ .../sdkuilib/repository/RepoSources.java | 147 ++++++++ .../sdkuilib/repository/UpdaterWindow.java | 354 +++++++++++------- 9 files changed, 1042 insertions(+), 169 deletions(-) create mode 100755 tools/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/SdkRepository.java delete mode 100755 tools/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/SdkRepositoryConstants.java create mode 100755 tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/ITaskMonitor.java create mode 100755 tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/ProgressTask.java create mode 100755 tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/RepoSource.java create mode 100755 tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/RepoSources.java diff --git a/tools/sdkmanager/app/src/com/android/sdkmanager/Main.java b/tools/sdkmanager/app/src/com/android/sdkmanager/Main.java index a5550b5be..f90b1309e 100644 --- a/tools/sdkmanager/app/src/com/android/sdkmanager/Main.java +++ b/tools/sdkmanager/app/src/com/android/sdkmanager/Main.java @@ -53,7 +53,7 @@ class Main { /** Path to the SDK folder. This is the parent of {@link #TOOLSDIR}. */ - private String mSdkFolder; + private String mOsSdkFolder; /** Logger object. Use this to print normal output, warnings or errors. */ private ISdkLog mSdkLog; /** The SDK manager parses the SDK folder and gives access to the content. */ @@ -131,18 +131,18 @@ class Main { File tools; if (toolsDirProp.length() > 0) { tools = new File(toolsDirProp); - mSdkFolder = tools.getParent(); + mOsSdkFolder = tools.getParent(); } else { try { tools = new File(".").getCanonicalFile(); - mSdkFolder = tools.getParent(); + mOsSdkFolder = tools.getParent(); } catch (IOException e) { // Will print an error below since mSdkFolder is not defined } } } - if (mSdkFolder == null) { + if (mOsSdkFolder == null) { errorAndExit("The tools directory property is not set, please make sure you are executing %1$s", SdkConstants.androidCmdName()); } @@ -172,7 +172,7 @@ class Main { * Does the basic SDK parsing required for all actions */ private void parseSdk() { - mSdkManager = SdkManager.createManager(mSdkFolder, mSdkLog); + mSdkManager = SdkManager.createManager(mOsSdkFolder, mSdkLog); if (mSdkManager == null) { errorAndExit("Unable to parse SDK content."); @@ -234,7 +234,9 @@ class Main { */ private void showMainWindow() { try { - UpdaterWindow window = new UpdaterWindow(); + UpdaterWindow window = new UpdaterWindow( + mOsSdkFolder, + false /*userCanChangeSdkRoot*/); window.open(); } catch (Exception e) { e.printStackTrace(); @@ -254,7 +256,7 @@ class Main { } IAndroidTarget target = targets[targetId - 1]; - ProjectCreator creator = new ProjectCreator(mSdkFolder, + ProjectCreator creator = new ProjectCreator(mOsSdkFolder, mSdkCommandLine.isVerbose() ? OutputLevel.VERBOSE : mSdkCommandLine.isSilent() ? OutputLevel.SILENT : OutputLevel.NORMAL, @@ -316,7 +318,7 @@ class Main { target = targets[targetId - 1]; } - ProjectCreator creator = new ProjectCreator(mSdkFolder, + ProjectCreator creator = new ProjectCreator(mOsSdkFolder, mSdkCommandLine.isVerbose() ? OutputLevel.VERBOSE : mSdkCommandLine.isSilent() ? OutputLevel.SILENT : OutputLevel.NORMAL, @@ -766,7 +768,7 @@ class Main { mSdkLog.printf("\n"); // empty line // get the list of possible hardware properties - File hardwareDefs = new File (mSdkFolder + File.separator + + File hardwareDefs = new File (mOsSdkFolder + File.separator + SdkConstants.OS_SDK_TOOLS_LIB_FOLDER, SdkConstants.FN_HARDWARE_INI); List list = HardwareProperties.parseHardwareDefinitions(hardwareDefs, null /*sdkLog*/); diff --git a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/SdkRepository.java b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/SdkRepository.java new file mode 100755 index 000000000..72cc4255d --- /dev/null +++ b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/SdkRepository.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php + * + * 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.sdklib.repository; + +import java.io.InputStream; + +/** + * Constants for the sdk-repository XML Schema + */ +public class SdkRepository { + + public static final String NS_SDK_REPOSITORY = + "http://schemas.android.com/sdk/android/repository/1"; //$NON-NLS-1$ + + public static final String NODE_VERSION = "version"; //$NON-NLS-1$ + public static final String NODE_REVISION = "revision"; //$NON-NLS-1$ + public static final String NODE_API_LEVEL = "api-level"; //$NON-NLS-1$ + public static final String NODE_VENDOR = "vendor"; //$NON-NLS-1$ + public static final String NODE_NAME = "name"; //$NON-NLS-1$ + public static final String NODE_TOOL = "tool"; //$NON-NLS-1$ + public static final String NODE_DOC = "doc"; //$NON-NLS-1$ + public static final String NODE_PLATFORM = "platform"; //$NON-NLS-1$ + public static final String NODE_ADD_ON = "add-on"; //$NON-NLS-1$ + public static final String NODE_SDK_REPOSITORY = "sdk-repository"; //$NON-NLS-1$ + + public static InputStream getXsdStream() { + return SdkRepository.class.getResourceAsStream("sdk-repository.xsd"); //$NON-NLS-1$ + } + +} diff --git a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/SdkRepositoryConstants.java b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/SdkRepositoryConstants.java deleted file mode 100755 index d10808f2e..000000000 --- a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/SdkRepositoryConstants.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php - * - * 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.sdklib.repository; - -import java.io.InputStream; - -/** - * Constants for the sdk-repository XML Schema - */ -public class SdkRepositoryConstants { - - public static final String NS_SDK_REPOSITORY = - "http://schemas.android.com/sdk/android/repository/1"; - - public static InputStream getXsdStream() { - return SdkRepositoryConstants.class.getResourceAsStream("sdk-repository.xsd"); - } - -} diff --git a/tools/sdkmanager/libs/sdklib/tests/com/android/sdklib/repository/TestSdkRepository.java b/tools/sdkmanager/libs/sdklib/tests/com/android/sdklib/repository/TestSdkRepository.java index fe30239ac..879f3e6b2 100755 --- a/tools/sdkmanager/libs/sdklib/tests/com/android/sdklib/repository/TestSdkRepository.java +++ b/tools/sdkmanager/libs/sdklib/tests/com/android/sdklib/repository/TestSdkRepository.java @@ -110,7 +110,7 @@ public class TestSdkRepository extends TestCase { /** Helper method that returns a validator for our XSD */ private Validator getValidator(CaptureErrorHandler handler) throws SAXException { - InputStream xsdStream = SdkRepositoryConstants.getXsdStream(); + InputStream xsdStream = SdkRepository.getXsdStream(); SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); Schema schema = factory.newSchema(new StreamSource(xsdStream)); Validator validator = schema.newValidator(); diff --git a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/ITaskMonitor.java b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/ITaskMonitor.java new file mode 100755 index 000000000..72375ab20 --- /dev/null +++ b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/ITaskMonitor.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php + * + * 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.sdkuilib.repository; + +import org.eclipse.swt.widgets.ProgressBar; + +/** + * A monitor interface for a {@link ProgressTask} + */ +interface ITaskMonitor { + + /** + * Sets the description in the current task dialog. + * This method can be invoke from a non-UI thread. + */ + public void setDescription(String description); + + /** + * Sets the result text in the current task dialog. + * This method can be invoked from a non-UI thread. + */ + public void setResult(String result); + + /** + * Sets the max value of the progress bar. + * This method can be invoke from a non-UI thread. + * + * @see ProgressBar#setMaximum(int) + */ + public void setProgressMax(int max); + + /** + * Increments the current value of the progress bar. + * + * This method can be invoked from a non-UI thread. + */ + public void incProgress(int delta); + + /** + * Returns true if the "Cancel" button was selected. + * It is up to the task thread to pool this and exit. + */ + public boolean cancelRequested(); + + +} diff --git a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/ProgressTask.java b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/ProgressTask.java new file mode 100755 index 000000000..47e21d796 --- /dev/null +++ b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/ProgressTask.java @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php + * + * 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.sdkuilib.repository; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +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.Dialog; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.ProgressBar; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +class ProgressTask extends Dialog + implements ITaskMonitor //$hide$ (hide from SWT designer) + { + + private boolean mCancelRequested; + private boolean mCloseRequested; + private boolean mAutomaticallyCloseOnTaskCompletion = true; + + + // UI fields + private Shell mDialogShell; + private Composite mRootComposite; + private Label mLabel; + private ProgressBar mProgressBar; + private Button mCancelButton; + private Text mResultText; + + + /** + * Create the dialog. + * @param parent Parent container + */ + public ProgressTask(Shell parent) { + super(parent, SWT.APPLICATION_MODAL); + } + + /** + * Open the dialog and blocks till it gets closed + */ + public void open() { + createContents(); + mDialogShell.open(); + mDialogShell.layout(); + Display display = getParent().getDisplay(); + + startTask(); //$hide$ (hide from SWT designer) + + while (!mDialogShell.isDisposed() && !mCloseRequested) { + if (!display.readAndDispatch()) { + display.sleep(); + } + } + if (!mDialogShell.isDisposed()) { + mDialogShell.close(); + } + } + + /** + * Create contents of the dialog. + */ + private void createContents() { + mDialogShell = new Shell(getParent(), SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL); + mDialogShell.setLayout(new GridLayout(1, false)); + mDialogShell.setSize(450, 300); + mDialogShell.setText(getText()); + + mRootComposite = new Composite(mDialogShell, SWT.NONE); + mRootComposite.setLayout(new GridLayout(2, false)); + mRootComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); + + mLabel = new Label(mRootComposite, SWT.NONE); + mLabel.setText("Task"); + mLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1)); + + mProgressBar = new ProgressBar(mRootComposite, SWT.NONE); + mProgressBar.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); + mCancelButton = new Button(mRootComposite, SWT.NONE); + mCancelButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); + mCancelButton.setText("Cancel"); + + mCancelButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + mCancelRequested = true; + mCancelButton.setEnabled(false); + } + }); + + mResultText = new Text(mRootComposite, + SWT.BORDER | SWT.READ_ONLY | SWT.V_SCROLL | SWT.MULTI); + mResultText.setEditable(true); + mResultText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1)); + mResultText.setVisible(false); + } + + // -- End of UI, Start of internal logic ---------- + // Hide everything down-below from SWT designer + //$hide>>$ + + public interface ThreadTask { + public abstract void PerformTask(ITaskMonitor monitor); + } + + private ThreadTask mTask; + + /** + * Creates a new {@link ProgressTask} with the given title. + * The given task will execute in a separate thread (not the UI thread). + * + * This blocks till the thread ends. + */ + public static ProgressTask start(Shell parent, String title, ThreadTask task) { + ProgressTask t = new ProgressTask(parent); + t.setText(title); + t.setTask(task); + t.open(); + return t; + } + + /** + * Sets the description in the current task dialog. + * This method can be invoke from a non-UI thread. + */ + public void setDescription(final String description) { + mDialogShell.getDisplay().asyncExec(new Runnable() { + public void run() { + if (!mLabel.isDisposed()) { + mLabel.setText(description); + } + } + }); + } + + /** + * Sets the description in the current task dialog. + * This method can be invoke from a non-UI thread. + */ + public void setResult(final String result) { + mAutomaticallyCloseOnTaskCompletion = false; + mDialogShell.getDisplay().asyncExec(new Runnable() { + public void run() { + if (!mResultText.isDisposed()) { + mResultText.setVisible(true); + mResultText.setText(result); + } + } + }); + } + + /** + * Sets the max value of the progress bar. + * This method can be invoke from a non-UI thread. + * + * @see ProgressBar#setMaximum(int) + */ + public void setProgressMax(final int max) { + mDialogShell.getDisplay().asyncExec(new Runnable() { + public void run() { + if (!mProgressBar.isDisposed()) { + mProgressBar.setMaximum(max); + } + } + }); + } + + /** + * Increments the current value of the progress bar. + * + * This method can be invoked from a non-UI thread. + */ + public void incProgress(final int delta) { + mDialogShell.getDisplay().asyncExec(new Runnable() { + public void run() { + if (!mProgressBar.isDisposed()) { + mProgressBar.setSelection(mProgressBar.getSelection() + delta); + } + } + }); + } + + /** + * Returns true if the "Cancel" button was selected. + * It is up to the task thread to pool this and exit. + */ + public boolean cancelRequested() { + return mCancelRequested; + } + + /** Sets the task that will execute in a separate thread. */ + private void setTask(ThreadTask task) { + mTask = task; + } + + /** + * Starts the task from {@link #setTask(ThreadTask)} in a separate thread. + * When the task completes, set {@link #mCloseRequested} to end the dialog loop. + */ + private void startTask() { + if (mTask != null) { + new Thread(getText()) { + @Override + public void run() { + mTask.PerformTask(ProgressTask.this); + if (mAutomaticallyCloseOnTaskCompletion) { + mCloseRequested = true; + } + } + }.start(); + } + } + + //$hide<<$ +} diff --git a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/RepoSource.java b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/RepoSource.java new file mode 100755 index 000000000..d2f65debd --- /dev/null +++ b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/RepoSource.java @@ -0,0 +1,316 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php + * + * 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.sdkuilib.repository; + +import com.android.sdklib.repository.SdkRepository; +import com.android.sdkuilib.repository.ProgressTask.ThreadTask; + +import org.eclipse.swt.widgets.Shell; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.StringReader; +import java.net.URL; +import java.util.ArrayList; + +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.stream.StreamSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import javax.xml.validation.Validator; + +/** + * + */ +class RepoSource { + + private final String mUrl; + private final boolean mAddonOnly; + + private ArrayList mPackages; + private String mDescription; + + /** + * Constructs a new source for the given repository URL. + */ + public RepoSource(String url, boolean addonOnly) { + mUrl = url; + mAddonOnly = addonOnly; + } + + @Override + public String toString() { + return mUrl; + } + + /** Returns the URL of the source repository. */ + public String getUrl() { + return mUrl; + } + + /** + * Returns the list of known packages. This is null when the source hasn't been loaded yet. + */ + public ArrayList getPackages() { + return mPackages; + } + + public String getDescription() { + return mDescription == null ? "" : mDescription; //$NON-NLS-1$ + } + + /** + * Tries to fetch the repository index for the given URL. + */ + public void load(Shell shell) { + + ProgressTask.start(shell, "Init SDK Updater", new ThreadTask() { + public void PerformTask(ITaskMonitor monitor) { + monitor.setProgressMax(4); + + monitor.setDescription(String.format("Fetching %1$s", mUrl)); + monitor.incProgress(1); + + String xml = fetchUrl(mUrl, monitor); + + if (xml == null) { + mDescription = String.format("Failed to fetch URL %1$s", mUrl); + return; + } + + monitor.setDescription("Validate XML"); + monitor.incProgress(1); + + if (!validateXml(xml, monitor)) { + mDescription = String.format("Failed to validate XML at %1$s", mUrl); + return; + } + + monitor.setDescription("Parse XML"); + monitor.incProgress(1); + parsePackages(xml, monitor); + + // done + monitor.incProgress(1); + } + }); + } + + /* + * References: + * Java URL Connection: http://java.sun.com/docs/books/tutorial/networking/urls/readingWriting.html + * Java URL Reader: http://java.sun.com/docs/books/tutorial/networking/urls/readingURL.html + * Java set Proxy: http://java.sun.com/docs/books/tutorial/networking/urls/_setProxy.html + */ + private String fetchUrl(String urlString, ITaskMonitor monitor) { + URL url; + try { + url = new URL(urlString); + + StringBuilder xml = new StringBuilder(); + InputStream is = null; + BufferedReader br = null; + try { + is = url.openStream(); + br = new BufferedReader(new InputStreamReader(is)); + + String line; + while ((line = br.readLine()) != null) { + xml.append(line); + } + + return xml.toString(); + + } finally { + if (br != null) { + try { + br.close(); + } catch (IOException e) { + // pass + } + } + + if (is != null) { + try { + is.close(); + } catch (IOException e) { + // pass + } + } + } + + } catch (IOException e) { + monitor.setResult(e.getMessage()); + } + + return null; + } + + private boolean validateXml(String xml, ITaskMonitor monitor) { + + try { + Validator validator = getValidator(); + validator.validate(new StreamSource(new StringReader(xml))); + return true; + + } catch (SAXException e) { + monitor.setResult(e.getMessage()); + + } catch (IOException e) { + monitor.setResult(e.getMessage()); + } + + return false; + } + + /** Helper method that returns a validator for our XSD */ + private Validator getValidator() throws SAXException { + InputStream xsdStream = SdkRepository.getXsdStream(); + SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + + // This may throw a SAX Exception if the schema itself is not a valid XSD + Schema schema = factory.newSchema(new StreamSource(xsdStream)); + + Validator validator = schema.newValidator(); + + return validator; + } + + + private boolean parsePackages(String xml, ITaskMonitor monitor) { + + try { + Document doc = getDocument(xml); + + Node root = getFirstChild(doc, SdkRepository.NODE_SDK_REPOSITORY); + if (root != null) { + + mPackages = new ArrayList(); + + for (Node child = root.getFirstChild(); + child != null; + child = child.getNextSibling()) { + if (child.getNodeType() == Node.ELEMENT_NODE && + child.getNamespaceURI().equals(SdkRepository.NS_SDK_REPOSITORY)) { + String name = child.getLocalName(); + if (SdkRepository.NODE_ADD_ON.equals(name)) { + parseAddon(child, mPackages, monitor); + + } else if (!mAddonOnly) { + if (SdkRepository.NODE_PLATFORM.equals(name)) { + parsePlatform(child, mPackages, monitor); + + } else if (SdkRepository.NODE_DOC.equals(name)) { + parseDoc(child, mPackages, monitor); + + } else if (SdkRepository.NODE_TOOL.equals(name)) { + parseTool(child, mPackages, monitor); + + } + } + } + } + + return true; + } + + } catch (ParserConfigurationException e) { + monitor.setResult("Failed to create XML document builder for %1$s"); + + } catch (SAXException e) { + monitor.setResult("Failed to parse XML document %1$s"); + + } catch (IOException e) { + monitor.setResult("Failed to read XML document"); + } + + return false; + } + + private Node getFirstChild(Node node, String xmlLocalName) { + + for(Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) { + if (child.getNodeType() == Node.ELEMENT_NODE && + child.getNamespaceURI().equals(SdkRepository.NS_SDK_REPOSITORY)) { + if (xmlLocalName == null || child.getLocalName().equals(xmlLocalName)) { + return child; + } + } + } + + return null; + } + + private Document getDocument(String xml) + throws ParserConfigurationException, SAXException, IOException { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setIgnoringComments(true); + factory.setNamespaceAware(true); + + DocumentBuilder builder = factory.newDocumentBuilder(); + Document doc = builder.parse(new InputSource(new StringReader(xml))); + + return doc; + } + + private void parseAddon(Node addon, ArrayList packages, ITaskMonitor monitor) { + // TODO Auto-generated method stub + String s = String.format("addon %1$s by %2$s, api %3$s, rev %4$s", + getFirstChild(addon, SdkRepository.NODE_NAME).getTextContent(), + getFirstChild(addon, SdkRepository.NODE_VENDOR).getTextContent(), + getFirstChild(addon, SdkRepository.NODE_API_LEVEL).getTextContent(), + getFirstChild(addon, SdkRepository.NODE_REVISION).getTextContent() + ); + packages.add(s); + } + + private void parsePlatform(Node platform, ArrayList packages, ITaskMonitor monitor) { + // TODO Auto-generated method stub + String s = String.format("platform %1$s, api %2$s, rev %3$s", + getFirstChild(platform, SdkRepository.NODE_VERSION).getTextContent(), + getFirstChild(platform, SdkRepository.NODE_API_LEVEL).getTextContent(), + getFirstChild(platform, SdkRepository.NODE_REVISION).getTextContent() + ); + packages.add(s); + } + + private void parseDoc(Node doc, ArrayList packages, ITaskMonitor monitor) { + // TODO Auto-generated method stub + String s = String.format("doc for api %1$s, rev %2$s", + getFirstChild(doc, SdkRepository.NODE_API_LEVEL).getTextContent(), + getFirstChild(doc, SdkRepository.NODE_REVISION).getTextContent() + ); + packages.add(s); + } + + private void parseTool(Node tool, ArrayList packages, ITaskMonitor monitor) { + // TODO Auto-generated method stub + String s = String.format("tool, rev %1$s", + getFirstChild(tool, SdkRepository.NODE_REVISION).getTextContent() + ); + packages.add(s); + } +} diff --git a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/RepoSources.java b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/RepoSources.java new file mode 100755 index 000000000..c06e16d10 --- /dev/null +++ b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/RepoSources.java @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php + * + * 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.sdkuilib.repository; + +import org.eclipse.jface.viewers.IContentProvider; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Shell; + +import java.util.ArrayList; + +/** + * + */ +class RepoSources { + + private Shell mShell; + private ArrayList mSources = new ArrayList(); + + public RepoSources() { + } + + public void setShell(Shell shell) { + mShell = shell; + } + + public void add(RepoSource source) { + mSources.add(source); + } + + public ILabelProvider getLabelProvider() { + return new ViewerLabelProvider(); + } + + + public IContentProvider getContentProvider() { + return new TreeContentProvider(); + } + + // ------------ + + public class ViewerLabelProvider extends LabelProvider { + /** Returns null by default */ + @Override + public Image getImage(Object element) { + return super.getImage(element); + } + + /** Returns the toString of the element. */ + @Override + public String getText(Object element) { + return super.getText(element); + } + } + + // ------------ + + private class TreeContentProvider implements ITreeContentProvider { + + private Object mInput; + + // Called when the viewer is disposed + public void dispose() { + // pass + } + + // Called when the input is set or changed on the provider + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + mInput = newInput; + // pass + } + + /** + * Called to collect the root elements for the given input. + * The input here is a {@link RepoSources} object, this returns an array + * of {@link RepoSource}. + */ + public Object[] getElements(Object inputElement) { + return getChildren(inputElement); + } + + /** + * Get the children of the given parent. This is requested on-demand as + * nodes are expanded. + * + * For a {@link RepoSources} object, returns an array of {@link RepoSource}. + * For a {@link RepoSource}, returns an array of packages. + */ + public Object[] getChildren(Object parentElement) { + if (parentElement instanceof RepoSources) { + return ((RepoSources) parentElement).mSources.toArray(); + + } else if (parentElement instanceof RepoSource) { + RepoSource source = (RepoSource) parentElement; + ArrayList pkgs = source.getPackages(); + + if (pkgs == null) { + source.load(mShell); + pkgs = source.getPackages(); + } + if (pkgs != null) { + return pkgs.toArray(); + } + } + + return new Object[0]; + } + + /** + * Returns the parent of a given element. + * The input {@link RepoSources} is the parent of all {@link RepoSource} elements. + */ + public Object getParent(Object element) { + if (element instanceof RepoSource) { + return mInput; + } + return null; + } + + /** + * Returns true if a given element has children, which is used to display a + * "+/expand" box next to the tree node. + * All {@link RepoSource} are expandable, whether they actually have any childre or not. + */ + public boolean hasChildren(Object element) { + return element instanceof RepoSource; + } + } + +} diff --git a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/UpdaterWindow.java b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/UpdaterWindow.java index 57537d2ae..27ebb6fd2 100755 --- a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/UpdaterWindow.java +++ b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/UpdaterWindow.java @@ -16,10 +16,14 @@ package com.android.sdkuilib.repository; +import com.android.sdkuilib.repository.ProgressTask.ThreadTask; + import org.eclipse.jface.viewers.CheckboxTreeViewer; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.TableTree; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; @@ -39,40 +43,54 @@ import org.eclipse.swt.widgets.TreeColumn; public class UpdaterWindow { - protected Shell mshlAndroidSdkUpdater; - private TabFolder tabFolder; - private TabItem mtbtmInstalledPackages; - private Composite compositeInst; - private TabItem mtbtmAvailablePackages; - private Composite compositeAvail; - private Text text; - private Button mbtnBrowse; - private Label mlblSdkLocation; - private Group mgrpDescription; - private Composite composite_3; - private Button mbtnUpdate; - private Button mbtnDelete; - private Button mbtnHomePage; - private Label placeholder1; - private Label placeholder2; - private Label mlblInstalledPackages; + private final String mOsSdkRoot; + private final boolean mUserCanChangeSdkRoot; + + private RepoSources mSources = new RepoSources(); + + // --- UI members --- + + protected Shell mAndroidSdkUpdater; + private TabFolder mTabFolder; + private TabItem mTabInstalledPkg; + private Composite mRootInst; + private TabItem mTabAvailPkg; + private Composite mRootAvail; + private Text mSdkLocText; + private Button mSdkLocBrowse; + private Label mSdkLocLabel; + private Group mInstDescription; + private Composite mInstButtons; + private Button mInstUpdate; + private Button mInstDelete; + private Button mInstHomePage; + private Label mPlaceholder1; + private Label mPlaceholder2; + private Label mInstalledPkgLabel; private TableTree tableTree; - private Tree tree; - private Button mbtnRemoveSite; - private Button mbtnAddSite; - private Label placeholder3; - private Button mbtnRefresh; - private Button mbtnInstallSelected; - private Group mgrpDescription_1; - private Table table; - private TableColumn mtblclmnSummary; - private TableColumn mtblclmnApiLevel; - private TableColumn mtblclmnRevision; - private TreeColumn mtrclmnSummary; - private TreeColumn mtrclmnApiLevel; - private TreeColumn mtrclmnRevision; - private TreeColumn mtrclmnOs; - private TreeColumn mtrclmnInstalled; + private Tree mTreeAvailPkg; + private Button mAvailRemoveSite; + private Button mAvailAddSite; + private Label mPlaceholder3; + private Button mAvailRefresh; + private Button mAvailInstallSelected; + private Group mAvailDescription; + private Table mTableInstPkg; + private TableColumn mColumnInstSummary; + private TableColumn mColumnInstApiLevel; + private TableColumn mColumnInstRevision; + private TreeColumn mColumnAvailSummary; + private TreeColumn mColumnAvailApiLevel; + private TreeColumn mColumnAvailRevision; + private TreeColumn mColumnAvailOs; + private TreeColumn mColumnAvailInstalled; + private CheckboxTreeViewer mTreeViewAvailPkg; + private TableViewer mTableViewerInstPkg; + + public UpdaterWindow(String osSdkRoot, boolean userCanChangeSdkRoot) { + mOsSdkRoot = osSdkRoot; + mUserCanChangeSdkRoot = userCanChangeSdkRoot; + } /** * Open the window. @@ -81,9 +99,10 @@ public class UpdaterWindow { public void open() { Display display = Display.getDefault(); createContents(); - mshlAndroidSdkUpdater.open(); - mshlAndroidSdkUpdater.layout(); - while (!mshlAndroidSdkUpdater.isDisposed()) { + mAndroidSdkUpdater.open(); + mAndroidSdkUpdater.layout(); + firstInit(); + while (!mAndroidSdkUpdater.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } @@ -94,129 +113,212 @@ public class UpdaterWindow { * Create contents of the window. */ protected void createContents() { - mshlAndroidSdkUpdater = new Shell(); - mshlAndroidSdkUpdater.setMinimumSize(new Point(200, 50)); - mshlAndroidSdkUpdater.setLayout(new GridLayout(1, false)); - mshlAndroidSdkUpdater.setSize(633, 433); - mshlAndroidSdkUpdater.setText("Android SDK Updater"); + mAndroidSdkUpdater = new Shell(); + mAndroidSdkUpdater.setMinimumSize(new Point(200, 50)); + mAndroidSdkUpdater.setLayout(new GridLayout(1, false)); + mAndroidSdkUpdater.setSize(633, 433); + mAndroidSdkUpdater.setText("Android SDK Updater"); - tabFolder = new TabFolder(mshlAndroidSdkUpdater, SWT.NONE); - tabFolder.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); + mTabFolder = new TabFolder(mAndroidSdkUpdater, SWT.NONE); + mTabFolder.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); - mtbtmInstalledPackages = new TabItem(tabFolder, SWT.NONE); - mtbtmInstalledPackages.setText("Installed Packages"); + createInstalledPackagesTab(); + createAvailablePackagesTab(); + } - compositeInst = new Composite(tabFolder, SWT.NONE); - compositeInst.setLayout(new GridLayout(3, false)); - mtbtmInstalledPackages.setControl(compositeInst); + private void createInstalledPackagesTab() { + mTabInstalledPkg = new TabItem(mTabFolder, SWT.NONE); + mTabInstalledPkg.setText("Installed Packages"); - mlblSdkLocation = new Label(compositeInst, SWT.NONE); - mlblSdkLocation.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); - mlblSdkLocation.setText("SDK Location:"); + mRootInst = new Composite(mTabFolder, SWT.NONE); + mRootInst.setLayout(new GridLayout(3, false)); + mTabInstalledPkg.setControl(mRootInst); - text = new Text(compositeInst, SWT.BORDER); - text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); + createSdkLocation(); - mbtnBrowse = new Button(compositeInst, SWT.NONE); - mbtnBrowse.setText("Browse..."); + mInstalledPkgLabel = new Label(mRootInst, SWT.NONE); + mInstalledPkgLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 3, 1)); + mInstalledPkgLabel.setText("Installed Packages:"); - mlblInstalledPackages = new Label(compositeInst, SWT.NONE); - mlblInstalledPackages.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 3, 1)); - mlblInstalledPackages.setText("Installed Packages:"); + mTableViewerInstPkg = new TableViewer(mRootInst, SWT.BORDER | SWT.FULL_SELECTION); + mTableInstPkg = mTableViewerInstPkg.getTable(); + mTableInstPkg.setHeaderVisible(true); + mTableInstPkg.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1)); - TableViewer tableInstalledPackage = new TableViewer(compositeInst, SWT.BORDER | SWT.FULL_SELECTION); - table = tableInstalledPackage.getTable(); - table.setHeaderVisible(true); - table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1)); + mColumnInstSummary = new TableColumn(mTableInstPkg, SWT.NONE); + mColumnInstSummary.setWidth(377); + mColumnInstSummary.setText("Summary"); - mtblclmnSummary = new TableColumn(table, SWT.NONE); - mtblclmnSummary.setWidth(377); - mtblclmnSummary.setText("Summary"); + mColumnInstApiLevel = new TableColumn(mTableInstPkg, SWT.NONE); + mColumnInstApiLevel.setWidth(100); + mColumnInstApiLevel.setText("API Level"); - mtblclmnApiLevel = new TableColumn(table, SWT.NONE); - mtblclmnApiLevel.setWidth(100); - mtblclmnApiLevel.setText("API Level"); + mColumnInstRevision = new TableColumn(mTableInstPkg, SWT.NONE); + mColumnInstRevision.setWidth(100); + mColumnInstRevision.setText("Revision"); - mtblclmnRevision = new TableColumn(table, SWT.NONE); - mtblclmnRevision.setWidth(100); - mtblclmnRevision.setText("Revision"); + mInstDescription = new Group(mRootInst, SWT.NONE); + mInstDescription.setText("Description"); + mInstDescription.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 3, 1)); - mgrpDescription = new Group(compositeInst, SWT.NONE); - mgrpDescription.setText("Description"); - mgrpDescription.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 3, 1)); + mInstButtons = new Composite(mRootInst, SWT.NONE); + mInstButtons.setLayout(new GridLayout(5, false)); + mInstButtons.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1)); - composite_3 = new Composite(compositeInst, SWT.NONE); - composite_3.setLayout(new GridLayout(5, false)); - composite_3.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1)); + mInstUpdate = new Button(mInstButtons, SWT.NONE); + mInstUpdate.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + onUpdateInstalledPackage(); + } + }); + mInstUpdate.setText("Update..."); - mbtnUpdate = new Button(composite_3, SWT.NONE); - mbtnUpdate.setText("Update..."); + mPlaceholder1 = new Label(mInstButtons, SWT.NONE); + mPlaceholder1.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 1, 1)); - placeholder1 = new Label(composite_3, SWT.NONE); - placeholder1.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 1, 1)); + mInstDelete = new Button(mInstButtons, SWT.NONE); + mInstDelete.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false, 1, 1)); + mInstDelete.setText("Delete..."); - mbtnDelete = new Button(composite_3, SWT.NONE); - mbtnDelete.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false, 1, 1)); - mbtnDelete.setText("Delete..."); + mPlaceholder2 = new Label(mInstButtons, SWT.NONE); + mPlaceholder2.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 1, 1)); - placeholder2 = new Label(composite_3, SWT.NONE); - placeholder2.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 1, 1)); + mInstHomePage = new Button(mInstButtons, SWT.NONE); + mInstHomePage.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); + mInstHomePage.setText("Home Page..."); + } - mbtnHomePage = new Button(composite_3, SWT.NONE); - mbtnHomePage.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); - mbtnHomePage.setText("Home Page..."); + private void createSdkLocation() { + mSdkLocLabel = new Label(mRootInst, SWT.NONE); + mSdkLocLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); + mSdkLocLabel.setText("SDK Location:"); - mtbtmAvailablePackages = new TabItem(tabFolder, SWT.NONE); - mtbtmAvailablePackages.setText("Available Packages"); + // If the sdk path is not user-customizable, do not create + // the browse button and use horizSpan=2 on the text field. - compositeAvail = new Composite(tabFolder, SWT.NONE); - compositeAvail.setLayout(new GridLayout(5, false)); - mtbtmAvailablePackages.setControl(compositeAvail); + mSdkLocText = new Text(mRootInst, SWT.BORDER); + mSdkLocText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); - CheckboxTreeViewer checkboxTreeAvailablePackages = new CheckboxTreeViewer(compositeAvail, SWT.BORDER); - tree = checkboxTreeAvailablePackages.getTree(); - tree.setHeaderVisible(true); - tree.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 5, 1)); + if (mUserCanChangeSdkRoot) { + mSdkLocBrowse = new Button(mRootInst, SWT.NONE); + mSdkLocBrowse.setText("Browse..."); + } else { + mSdkLocText.setEditable(false); + ((GridData)mSdkLocText.getLayoutData()).horizontalSpan++; + } - mtrclmnSummary = new TreeColumn(tree, SWT.NONE); - mtrclmnSummary.setWidth(289); - mtrclmnSummary.setText("Summary"); + mSdkLocText.setText(mOsSdkRoot); + } - mtrclmnApiLevel = new TreeColumn(tree, SWT.NONE); - mtrclmnApiLevel.setWidth(66); - mtrclmnApiLevel.setText("API Level"); + private void createAvailablePackagesTab() { + mTabAvailPkg = new TabItem(mTabFolder, SWT.NONE); + mTabAvailPkg.setText("Available Packages"); - mtrclmnRevision = new TreeColumn(tree, SWT.NONE); - mtrclmnRevision.setWidth(63); - mtrclmnRevision.setText("Revision"); + mRootAvail = new Composite(mTabFolder, SWT.NONE); + mRootAvail.setLayout(new GridLayout(5, false)); + mTabAvailPkg.setControl(mRootAvail); - mtrclmnOs = new TreeColumn(tree, SWT.NONE); - mtrclmnOs.setWidth(100); - mtrclmnOs.setText("OS/Arch"); + mTreeViewAvailPkg = new CheckboxTreeViewer(mRootAvail, SWT.BORDER); + mTreeViewAvailPkg.setContentProvider(mSources.getContentProvider()); + mTreeViewAvailPkg.setLabelProvider(mSources.getLabelProvider()); + mTreeAvailPkg = mTreeViewAvailPkg.getTree(); + mTreeAvailPkg.setHeaderVisible(true); + mTreeAvailPkg.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 5, 1)); - mtrclmnInstalled = new TreeColumn(tree, SWT.NONE); - mtrclmnInstalled.setWidth(59); - mtrclmnInstalled.setText("Installed"); + mColumnAvailSummary = new TreeColumn(mTreeAvailPkg, SWT.NONE); + mColumnAvailSummary.setWidth(289); + mColumnAvailSummary.setText("Summary"); - mgrpDescription_1 = new Group(compositeAvail, SWT.NONE); - mgrpDescription_1.setText("Description"); - mgrpDescription_1.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 5, 1)); + mColumnAvailApiLevel = new TreeColumn(mTreeAvailPkg, SWT.NONE); + mColumnAvailApiLevel.setWidth(66); + mColumnAvailApiLevel.setText("API Level"); - mbtnAddSite = new Button(compositeAvail, SWT.NONE); - mbtnAddSite.setText("Add Site..."); + mColumnAvailRevision = new TreeColumn(mTreeAvailPkg, SWT.NONE); + mColumnAvailRevision.setWidth(63); + mColumnAvailRevision.setText("Revision"); - mbtnRemoveSite = new Button(compositeAvail, SWT.NONE); - mbtnRemoveSite.setText("Delete Site..."); + mColumnAvailOs = new TreeColumn(mTreeAvailPkg, SWT.NONE); + mColumnAvailOs.setWidth(100); + mColumnAvailOs.setText("OS/Arch"); - placeholder3 = new Label(compositeAvail, SWT.NONE); - placeholder3.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, false, 1, 1)); + mColumnAvailInstalled = new TreeColumn(mTreeAvailPkg, SWT.NONE); + mColumnAvailInstalled.setWidth(59); + mColumnAvailInstalled.setText("Installed"); - mbtnRefresh = new Button(compositeAvail, SWT.NONE); - mbtnRefresh.setText("Refresh"); + mAvailDescription = new Group(mRootAvail, SWT.NONE); + mAvailDescription.setText("Description"); + mAvailDescription.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 5, 1)); - mbtnInstallSelected = new Button(compositeAvail, SWT.NONE); - mbtnInstallSelected.setText("Install Selected"); + mAvailAddSite = new Button(mRootAvail, SWT.NONE); + mAvailAddSite.setText("Add Site..."); + mAvailRemoveSite = new Button(mRootAvail, SWT.NONE); + mAvailRemoveSite.setText("Delete Site..."); + + mPlaceholder3 = new Label(mRootAvail, SWT.NONE); + mPlaceholder3.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, false, 1, 1)); + + mAvailRefresh = new Button(mRootAvail, SWT.NONE); + mAvailRefresh.setText("Refresh"); + + mAvailInstallSelected = new Button(mRootAvail, SWT.NONE); + mAvailInstallSelected.setText("Install Selected"); + } + + // --- UI Callbacks ----------- + + protected void onUpdateInstalledPackage() { + ProgressTask.start(getShell(), "Test", new ThreadTask() { + public void PerformTask(ITaskMonitor monitor) { + monitor.setDescription("Test"); + monitor.setProgressMax(100); + int n = 0; + int d = 1; + while(!monitor.cancelRequested()) { + monitor.incProgress(d); + n += d; + if (n == 0 || n == 100) d = -d; + try { + Thread.sleep(5); + } catch (InterruptedException e) { + } + } + } + }); + } + + + // -------------- + + private Shell getShell() { + return mAndroidSdkUpdater; + } + + /** + * Once the UI has been created, initialize the content + */ + private void firstInit() { + + setupSources(); + scanLocalSdkFolders(); + } + + private void setupSources() { + mSources.setShell(getShell()); + + mSources.add(new RepoSource( + "https://dl.google.com/android/eclipse/repository/index.xml", //$NON-NLS-1$ + false /* addonOnly */)); + mSources.add(new RepoSource( + "http://www.corp.google.com/~raphael/android/sdk-repo/repository.xml", //$NON-NLS-1$ + false /* addonOnly */)); + + mTreeViewAvailPkg.setInput(mSources); + } + + private void scanLocalSdkFolders() { + // TODO Auto-generated method stub } }