From e2c0e975c244290674db1eb42e27bc03eb8d3b77 Mon Sep 17 00:00:00 2001 From: Raphael Date: Thu, 21 May 2009 21:43:00 -0700 Subject: SDK Updater: some refactoring and some new features. The refactoring part involves moving as much as possible stuff in SdkLib/internal/repository. The UI has moved in SdkUiLib/internal/repository except a specific public wrapper for calling the Sdk Updater window. There are also a bunch of new classes to handle the internal structures: Package is the base type and to match the XML element names we have PlatformPackage, AddonPackage, DocPackage and ToolPackage. All headers have been fixed. --- .../sdklib/internal/repository/AddonPackage.java | 54 ++++ .../sdklib/internal/repository/DocPackage.java | 29 ++ .../sdklib/internal/repository/IDescription.java | 40 +++ .../android/sdklib/internal/repository/ITask.java | 26 ++ .../sdklib/internal/repository/ITaskFactory.java | 25 ++ .../sdklib/internal/repository/ITaskMonitor.java | 63 ++++ .../sdklib/internal/repository/Package.java | 92 ++++++ .../internal/repository/PlatformPackage.java | 46 +++ .../sdklib/internal/repository/RepoSource.java | 331 +++++++++++++++++++++ .../sdklib/internal/repository/ToolPackage.java | 40 +++ .../android/sdklib/repository/SdkRepository.java | 60 +++- .../src/com/android/sdkuilib/AvdSelector.java | 4 +- .../com/android/sdkuilib/SdkTargetSelector.java | 54 ++-- .../internal/repository/AvailablePackagesPage.java | 177 +++++++++++ .../internal/repository/InstalledPackagesPage.java | 200 +++++++++++++ .../sdkuilib/internal/repository/ProgressTask.java | 251 ++++++++++++++++ .../internal/repository/ProgressTaskFactory.java | 39 +++ .../sdkuilib/internal/repository/RepoSources.java | 155 ++++++++++ .../sdkuilib/internal/repository/UpdaterData.java | 51 ++++ .../internal/repository/UpdaterWindowImpl.java | 223 ++++++++++++++ .../internal/repository/android_icon_16.png | Bin 0 -> 460 bytes .../sdkuilib/repository/AvailablePackagesPage.java | 116 -------- .../android/sdkuilib/repository/ITaskMonitor.java | 60 ---- .../sdkuilib/repository/InstalledPackagesPage.java | 168 ----------- .../android/sdkuilib/repository/ProgressTask.java | 236 --------------- .../android/sdkuilib/repository/RepoSource.java | 316 -------------------- .../android/sdkuilib/repository/RepoSources.java | 147 --------- .../android/sdkuilib/repository/UpdaterWindow.java | 235 ++------------- .../sdkuilib/repository/android_icon_16.png | Bin 460 -> 0 bytes 29 files changed, 1939 insertions(+), 1299 deletions(-) create mode 100755 sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/AddonPackage.java create mode 100755 sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/DocPackage.java create mode 100755 sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/IDescription.java create mode 100755 sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ITask.java create mode 100755 sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ITaskFactory.java create mode 100755 sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ITaskMonitor.java create mode 100755 sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Package.java create mode 100755 sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/PlatformPackage.java create mode 100755 sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/RepoSource.java create mode 100755 sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ToolPackage.java create mode 100755 sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/AvailablePackagesPage.java create mode 100755 sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/InstalledPackagesPage.java create mode 100755 sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ProgressTask.java create mode 100755 sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ProgressTaskFactory.java create mode 100755 sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/RepoSources.java create mode 100755 sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterData.java create mode 100755 sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterWindowImpl.java create mode 100755 sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/android_icon_16.png delete mode 100755 sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/AvailablePackagesPage.java delete mode 100755 sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/ITaskMonitor.java delete mode 100755 sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/InstalledPackagesPage.java delete mode 100755 sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/ProgressTask.java delete mode 100755 sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/RepoSource.java delete mode 100755 sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/RepoSources.java delete mode 100755 sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/android_icon_16.png (limited to 'sdkmanager') diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/AddonPackage.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/AddonPackage.java new file mode 100755 index 0000000..eb016cd --- /dev/null +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/AddonPackage.java @@ -0,0 +1,54 @@ +/* + * 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.sdklib.internal.repository; + +import com.android.sdklib.repository.SdkRepository; + +import org.w3c.dom.Node; + +/** + * + */ +public class AddonPackage extends Package { + + private final String mVendor; + private final String mName; + private final String mApiLevel; + + public AddonPackage(Node packageNode) { + super(packageNode); + mVendor = getXmlString(packageNode, SdkRepository.NODE_VENDOR); + mName = getXmlString(packageNode, SdkRepository.NODE_NAME); + mApiLevel = getXmlString(packageNode, SdkRepository.NODE_API_LEVEL); + + // TODO libs + } + + public String getVendor() { + return mVendor; + } + + public String getName() { + return mName; + } + + public String getApiLevel() { + return mApiLevel; + } + + +} diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/DocPackage.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/DocPackage.java new file mode 100755 index 0000000..fa71d4f --- /dev/null +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/DocPackage.java @@ -0,0 +1,29 @@ +/* + * 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.sdklib.internal.repository; + +import org.w3c.dom.Node; + +/** + * + */ +public class DocPackage extends Package { + + public DocPackage(Node packageNode) { + super(packageNode); + } +} diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/IDescription.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/IDescription.java new file mode 100755 index 0000000..7af92e2 --- /dev/null +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/IDescription.java @@ -0,0 +1,40 @@ +/* + * 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.sdklib.internal.repository; + +/** + * Interface for elements that can provide a description of themselves. + */ +public interface IDescription { + + /** + * Returns a description of the given element. Cannot be null. + *

+ * A description is a multi-line of text, typically much more + * elaborate than what {@link #toString()} would provide. + */ + public abstract String getShortDescription(); + + /** + * Returns a description of the given element. Cannot be null. + *

+ * A description is a multi-line of text, typically much more + * elaborate than what {@link #toString()} would provide. + */ + public abstract String getLongDescription(); + +} diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ITask.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ITask.java new file mode 100755 index 0000000..9178460 --- /dev/null +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ITask.java @@ -0,0 +1,26 @@ +/* + * 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.sdklib.internal.repository; + + +/** + * A task that executes and can update a monitor to display its status. + * The task will generally be run in a separate thread. + */ +public interface ITask { + public abstract void run(ITaskMonitor monitor); +} diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ITaskFactory.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ITaskFactory.java new file mode 100755 index 0000000..540825c --- /dev/null +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ITaskFactory.java @@ -0,0 +1,25 @@ +/* + * 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.sdklib.internal.repository; + +/** + * A factory that can start and run new {@link ITask}s. + */ +public interface ITaskFactory { + + public abstract void start(String title, ITask task); +} diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ITaskMonitor.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ITaskMonitor.java new file mode 100755 index 0000000..832d246 --- /dev/null +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ITaskMonitor.java @@ -0,0 +1,63 @@ +/* + * 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.sdklib.internal.repository; + + +/** + * A monitor interface for a {@link ITask}. + *

+ * Depending on the task factory that created the task, there might not be any UI + * or it might not implement all the methods, in which case calling them would be + * a no-op but is guaranteed not to crash. + *

+ * If the task runs in a non-UI worker thread, the task factory implementation + * will take care of the update the UI in the correct thread. The task itself + * must not have to deal with it. + */ +public interface ITaskMonitor { + + /** + * Sets the description in the current task dialog. + * This method can be invoked 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 invoked from a non-UI thread. + */ + 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 user requested to cancel the operation. + * It is up to the task thread to pool this and exit as soon + * as possible. + */ + public boolean cancelRequested(); +} diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Package.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Package.java new file mode 100755 index 0000000..126694a --- /dev/null +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Package.java @@ -0,0 +1,92 @@ +/* + * 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.sdklib.internal.repository; + +import com.android.sdklib.repository.SdkRepository; + +import org.w3c.dom.Node; + +/** + * + */ +public class Package { + + private final int mRevision; + private final String mDescription; + private final String mDescUrl; + + private Package(int revision, String description, String descUrl) { + mRevision = revision; + mDescription = description; + mDescUrl = descUrl; + } + + public Package(Node packageNode) { + this(getXmlInt (packageNode, SdkRepository.NODE_REVISION, 0), + getXmlString(packageNode, SdkRepository.NODE_DESCRIPTION), + getXmlString(packageNode, SdkRepository.NODE_DESC_URL)); + + // TODO archives + } + + /** The revision, an int > 0, for all packages (platform, add-on, tool, doc). */ + public int getRevision() { + return mRevision; + } + + /** The optional description for all packages (platform, add-on, tool, doc) or for a lib. */ + public String getDescription() { + return mDescription; + } + + /** The optional description URL for all packages (platform, add-on, tool, doc). + * Can be empty but not null. */ + public String getDescUrl() { + return mDescUrl; + } + + /** + * Retrieves the value of that XML element as a string. + * Returns an empty string when the element is missing. + */ + protected static String getXmlString(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.getTextContent(); + } + } + } + + return ""; + } + + /** + * Retrieves the value of that XML element as an integer. + * Returns the default value when the element is missing or is not an integer. + */ + protected static int getXmlInt(Node node, String xmlLocalName, int defaultValue) { + String s = getXmlString(node, xmlLocalName); + try { + return Integer.parseInt(s); + } catch (NumberFormatException e) { + return defaultValue; + } + } + +} diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/PlatformPackage.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/PlatformPackage.java new file mode 100755 index 0000000..b798ea8 --- /dev/null +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/PlatformPackage.java @@ -0,0 +1,46 @@ +/* + * 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.sdklib.internal.repository; + +import com.android.sdklib.repository.SdkRepository; + +import org.w3c.dom.Node; + +/** + * + */ +public class PlatformPackage extends Package { + + private final String mVersion; + private final String mApiLevel; + + public PlatformPackage(Node packageNode) { + super(packageNode); + mVersion = getXmlString(packageNode, SdkRepository.NODE_VERSION); + mApiLevel = getXmlString(packageNode, SdkRepository.NODE_API_LEVEL); + } + + public String getVersion() { + return mVersion; + } + + public String getApiLevel() { + return mApiLevel; + } + + +} diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/RepoSource.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/RepoSource.java new file mode 100755 index 0000000..fd909ab --- /dev/null +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/RepoSource.java @@ -0,0 +1,331 @@ +/* + * 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.sdklib.internal.repository; + +import com.android.sdklib.repository.SdkRepository; + +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; + +/** + * An sdk-repository source. It may be a full repository or an add-on only repository. + */ +public class RepoSource implements IDescription { + + 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; + setDefaultDescription(); + } + + /** 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 getShortDescription() { + return mUrl; + } + + public String getLongDescription() { + return mDescription == null ? "" : mDescription; //$NON-NLS-1$ + } + + /** + * Tries to fetch the repository index for the given URL. + */ + public void load(ITaskFactory taskFactory) { + + taskFactory.start("Init SDK Updater", new ITask() { + public void run(ITaskMonitor monitor) { + monitor.setProgressMax(4); + + setDefaultDescription(); + + monitor.setDescription(String.format("Fetching %1$s", mUrl)); + monitor.incProgress(1); + + String xml = fetchUrl(mUrl, monitor); + + if (xml == null) { + mDescription += String.format("\nFailed to fetch URL %1$s", mUrl); + return; + } + + monitor.setDescription("Validate XML"); + monitor.incProgress(1); + + if (!validateXml(xml, monitor)) { + mDescription += String.format("\nFailed to validate XML at %1$s", mUrl); + return; + } + + monitor.setDescription("Parse XML"); + monitor.incProgress(1); + parsePackages(xml, monitor); + if (mPackages.size() == 0) { + mDescription += "\nNo packages found."; + } else if (mPackages.size() == 1) { + mDescription += "\nOne package found."; + } else { + mDescription += String.format("\n%1$d packages found.", mPackages.size()); + } + + // done + monitor.incProgress(1); + } + }); + } + + private void setDefaultDescription() { + if (mAddonOnly) { + mDescription = String.format("Add-on Source: %1$s", mUrl); + } else { + mDescription = String.format("SDK Source: %1$s", mUrl); + } + } + + /* + * 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/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ToolPackage.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ToolPackage.java new file mode 100755 index 0000000..9979ee3 --- /dev/null +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ToolPackage.java @@ -0,0 +1,40 @@ +/* + * 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.sdklib.internal.repository; + +import com.android.sdklib.repository.SdkRepository; + +import org.w3c.dom.Node; + +/** + * + */ +public class ToolPackage extends Package { + + private final String mApiLevel; + + public ToolPackage(Node packageNode) { + super(packageNode); + mApiLevel = getXmlString(packageNode, SdkRepository.NODE_API_LEVEL); + } + + public String getApiLevel() { + return mApiLevel; + } + + +} diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/SdkRepository.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/SdkRepository.java index 72cc425..65962c9 100755 --- a/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/SdkRepository.java +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/SdkRepository.java @@ -19,24 +19,64 @@ package com.android.sdklib.repository; import java.io.InputStream; /** - * Constants for the sdk-repository XML Schema + * Public constants for the sdk-repository XML Schema. */ public class SdkRepository { + /** The XML namespace of the sdk-repository XML. */ 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$ + /** The root sdk-repository element */ public static final String NODE_SDK_REPOSITORY = "sdk-repository"; //$NON-NLS-1$ + /** A platform package. */ + public static final String NODE_PLATFORM = "platform"; //$NON-NLS-1$ + /** An add-on package. */ + public static final String NODE_ADD_ON = "add-on"; //$NON-NLS-1$ + /** A tool package. */ + public static final String NODE_TOOL = "tool"; //$NON-NLS-1$ + /** A doc package. */ + public static final String NODE_DOC = "doc"; //$NON-NLS-1$ + + /** The revision, an int > 0, for all packages (platform, add-on, tool, doc). */ + public static final String NODE_REVISION = "revision"; //$NON-NLS-1$ + /** The optional description for all packages (platform, add-on, tool, doc) or for a lib. */ + public static final String NODE_DESCRIPTION = "description"; //$NON-NLS-1$ + /** The optional description URL for all packages (platform, add-on, tool, doc). */ + public static final String NODE_DESC_URL = "desc-url"; //$NON-NLS-1$ + + /** The version, a string, for platform packages. */ + public static final String NODE_VERSION = "version"; //$NON-NLS-1$ + /** The api-level, an int > 0, for platform, add-on and doc packages. */ + public static final String NODE_API_LEVEL = "api-level"; //$NON-NLS-1$ + /** The vendor, a string, for add-on packages. */ + public static final String NODE_VENDOR = "vendor"; //$NON-NLS-1$ + /** The name, a string, for add-on packages or for libraries. */ + public static final String NODE_NAME = "name"; //$NON-NLS-1$ + + /** The libs container, optional for an add-on. */ + public static final String NODE_LIBS = "libs"; //$NON-NLS-1$ + /** A lib element in a libs container. */ + public static final String NODE_LIB = "lib"; //$NON-NLS-1$ + + /** The archives container, for all packages. */ + public static final String NODE_ARCHVIES = "archives"; //$NON-NLS-1$ + /** An archive element, for the archives container. */ + public static final String NODE_ARCHVIE = "archive"; //$NON-NLS-1$ + + /** An archive size, an int > 0. */ + public static final String NODE_SIZE = "size"; //$NON-NLS-1$ + /** A sha1 archive checksum, as a 40-char hex. */ + public static final String NODE_CHECKSUM = "checksum"; //$NON-NLS-1$ + /** A download archive URL, either absolute or relative to the repository xml. */ + public static final String NODE_URL = "url"; //$NON-NLS-1$ + + /** An archive OS attribute, mandatory. */ + public static final String NODE_OS = "os"; //$NON-NLS-1$ + /** An optional archive Architecture attribute. */ + public static final String NODE_ARCH = "arch"; //$NON-NLS-1$ + public static InputStream getXsdStream() { return SdkRepository.class.getResourceAsStream("sdk-repository.xsd"); //$NON-NLS-1$ } diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/AvdSelector.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/AvdSelector.java index 44c7724..0166556 100644 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/AvdSelector.java +++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/AvdSelector.java @@ -1,11 +1,11 @@ /* * Copyright (C) 2009 The Android Open Source Project * - * Licensed under the Eclipse Public License, Version 1.0 (the "License"); + * 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.eclipse.org/org/documents/epl-v10.php + * 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, diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/SdkTargetSelector.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/SdkTargetSelector.java index b23c865..b90bd61 100644 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/SdkTargetSelector.java +++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/SdkTargetSelector.java @@ -1,11 +1,11 @@ /* - * Copyright (C) 2008 The Android Open Source Project + * Copyright (C) 2009 The Android Open Source Project * - * Licensed under the Eclipse Public License, Version 1.0 (the "License"); + * 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.eclipse.org/org/documents/epl-v10.php + * 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, @@ -46,17 +46,17 @@ import org.eclipse.swt.widgets.TableItem; * selection. */ public class SdkTargetSelector { - + private IAndroidTarget[] mTargets; private final boolean mAllowSelection; private SelectionListener mSelectionListener; private Table mTable; private Label mDescription; private Composite mInnerGroup; - + /** * Creates a new SDK Target Selector. - * + * * @param parent The parent composite where the selector will be added. * @param targets The list of targets. This is not copied, the caller must not modify. * Targets can be null or an empty array, in which case the table is disabled. @@ -67,7 +67,7 @@ public class SdkTargetSelector { /** * Creates a new SDK Target Selector. - * + * * @param parent The parent composite where the selector will be added. * @param targets The list of targets. This is not copied, the caller must not modify. * Targets can be null or an empty array, in which case the table is disabled. @@ -79,7 +79,7 @@ public class SdkTargetSelector { mInnerGroup.setLayout(new GridLayout()); mInnerGroup.setLayoutData(new GridData(GridData.FILL_BOTH)); mInnerGroup.setFont(parent.getFont()); - + mAllowSelection = allowSelection; int style = SWT.BORDER | SWT.SINGLE | SWT.FULL_SELECTION; if (allowSelection) { @@ -137,7 +137,7 @@ public class SdkTargetSelector { /** * Changes the targets of the SDK Target Selector. - * + * * @param targets The list of targets. This is not copied, the caller must not modify. */ public void setTargets(IAndroidTarget[] targets) { @@ -154,19 +154,19 @@ public class SdkTargetSelector { * The {@link TableItem#getData()} contains an {@link IAndroidTarget}. *

* It is recommended that the caller uses the {@link #getSelected()} method instead. - * + * * @param selectionListener The new listener or null to remove it. */ public void setSelectionListener(SelectionListener selectionListener) { mSelectionListener = selectionListener; } - + /** * Sets the current target selection. *

* If the selection is actually changed, this will invoke the selection listener * (if any) with a null event. - * + * * @param target the target to be selection * @return true if the target could be selected, false otherwise. */ @@ -174,7 +174,7 @@ public class SdkTargetSelector { if (!mAllowSelection) { return false; } - + boolean found = false; boolean modified = false; @@ -192,17 +192,17 @@ public class SdkTargetSelector { } } } - + if (modified && mSelectionListener != null) { mSelectionListener.widgetSelected(null); } - + return found; } /** * Returns the selected item. - * + * * @return The selected item or null. */ public IAndroidTarget getSelected() { @@ -234,7 +234,7 @@ public class SdkTargetSelector { @Override public void controlResized(ControlEvent e) { Rectangle r = table.getClientArea(); - column0.setWidth(r.width * 30 / 100); // 30% + column0.setWidth(r.width * 30 / 100); // 30% column1.setWidth(r.width * 45 / 100); // 45% column2.setWidth(r.width * 15 / 100); // 15% column3.setWidth(r.width * 10 / 100); // 10% @@ -267,7 +267,7 @@ public class SdkTargetSelector { mSelectionListener.widgetDefaultSelected(e); } } - + public void widgetSelected(SelectionEvent e) { if (e.item instanceof TableItem) { TableItem i = (TableItem) e.item; @@ -315,7 +315,7 @@ public class SdkTargetSelector { } table.removeAll(); - + if (mTargets != null && mTargets.length > 0) { table.setEnabled(true); for (IAndroidTarget target : mTargets) { @@ -350,36 +350,36 @@ public class SdkTargetSelector { } /* - * Reference: + * Reference: * http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet125.java?view=markup */ - + final Listener listener = new Listener() { public void handleEvent(Event event) { - + switch(event.type) { case SWT.KeyDown: case SWT.MouseExit: case SWT.MouseDown: return; - + case SWT.MouseHover: updateDescription(table.getItem(new Point(event.x, event.y))); break; - + case SWT.Selection: if (event.item instanceof TableItem) { updateDescription((TableItem) event.item); } break; - + default: return; } } }; - + table.addListener(SWT.Dispose, listener); table.addListener(SWT.KeyDown, listener); table.addListener(SWT.MouseMove, listener); @@ -414,5 +414,5 @@ public class SdkTargetSelector { enableControl(c2, enabled); } } - + } diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/AvailablePackagesPage.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/AvailablePackagesPage.java new file mode 100755 index 0000000..97b8c0d --- /dev/null +++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/AvailablePackagesPage.java @@ -0,0 +1,177 @@ +/* + * 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.sdkuilib.internal.repository; + + +import com.android.sdklib.internal.repository.IDescription; + +import org.eclipse.jface.viewers.CheckboxTreeViewer; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ITreeSelection; +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.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeColumn; + +/* + * TODO list + * - check source => toggle packages: all, none + * - check package => set source check to tri-state + * - check callback => install enable if has selection + * - fill columns (or remove them?) + * - select tree item: delete site enable if add-on source + * - select tree item: refresh enable if source + * - load add-on sites from pref + * - delete site callback, update pref + * - refresh callback + * - install selected callback + */ + +public class AvailablePackagesPage extends Composite { + + private final UpdaterData mUpdaterData; + + private CheckboxTreeViewer mTreeViewerSources; + private Tree mTreeSources; + private TreeColumn mColumnAvailSummary; + private TreeColumn mColumnAvailApiLevel; + private TreeColumn mColumnAvailRevision; + private TreeColumn mColumnAvailOs; + private TreeColumn mColumnAvailInstalled; + private Group mDescriptionContainer; + private Button mAddSiteButton; + private Button mRemoveSiteButton; + private Label mPlaceholder3; + private Button mRefreshButton; + private Button mInstallSelectedButton; + private Label mDescriptionLabel; + + + /** + * Create the composite. + * @param parent The parent of the composite. + * @param updaterData An instance of {@link UpdaterData}. If null, a local + * one will be allocated just to help with the SWT Designer. + */ + public AvailablePackagesPage(Composite parent, UpdaterData updaterData) { + super(parent, SWT.BORDER); + + mUpdaterData = updaterData != null ? updaterData : new UpdaterData(); + + createContents(this); + } + + private void createContents(Composite parent) { + parent.setLayout(new GridLayout(5, false)); + + mTreeViewerSources = new CheckboxTreeViewer(parent, SWT.BORDER); + mTreeViewerSources.setContentProvider(mUpdaterData.getSources().getContentProvider()); + mTreeViewerSources.setLabelProvider(mUpdaterData.getSources().getLabelProvider()); + mTreeSources = mTreeViewerSources.getTree(); + mTreeSources.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + onTreeSelected(); //$hide$ + } + }); + mTreeSources.setHeaderVisible(true); + mTreeSources.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 5, 1)); + + mColumnAvailSummary = new TreeColumn(mTreeSources, SWT.NONE); + mColumnAvailSummary.setWidth(289); + mColumnAvailSummary.setText("Summary"); + + mColumnAvailApiLevel = new TreeColumn(mTreeSources, SWT.NONE); + mColumnAvailApiLevel.setWidth(66); + mColumnAvailApiLevel.setText("API Level"); + + mColumnAvailRevision = new TreeColumn(mTreeSources, SWT.NONE); + mColumnAvailRevision.setWidth(63); + mColumnAvailRevision.setText("Revision"); + + mColumnAvailOs = new TreeColumn(mTreeSources, SWT.NONE); + mColumnAvailOs.setWidth(100); + mColumnAvailOs.setText("OS/Arch"); + + mColumnAvailInstalled = new TreeColumn(mTreeSources, SWT.NONE); + mColumnAvailInstalled.setWidth(59); + mColumnAvailInstalled.setText("Installed"); + + mDescriptionContainer = new Group(parent, SWT.NONE); + mDescriptionContainer.setLayout(new GridLayout(1, false)); + mDescriptionContainer.setText("Description"); + mDescriptionContainer.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 5, 1)); + + mDescriptionLabel = new Label(mDescriptionContainer, SWT.NONE); + mDescriptionLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); + mDescriptionLabel.setText("Line1\nLine2\nLine3"); + + mAddSiteButton = new Button(parent, SWT.NONE); + mAddSiteButton.setText("Add Site..."); + + mRemoveSiteButton = new Button(parent, SWT.NONE); + mRemoveSiteButton.setText("Delete Site..."); + + mPlaceholder3 = new Label(parent, SWT.NONE); + mPlaceholder3.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, false, 1, 1)); + + mRefreshButton = new Button(parent, SWT.NONE); + mRefreshButton.setText("Refresh"); + + mInstallSelectedButton = new Button(parent, SWT.NONE); + mInstallSelectedButton.setText("Install Selected"); + } + + @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>>$ + + public void setInput(RepoSources sources) { + mTreeViewerSources.setInput(sources); + onTreeSelected(); + } + + private void onTreeSelected() { + ISelection sel = mTreeViewerSources.getSelection(); + if (sel instanceof ITreeSelection) { + Object elem = ((ITreeSelection) sel).getFirstElement(); + if (elem instanceof IDescription) { + mDescriptionLabel.setText(((IDescription) elem).getLongDescription()); + mDescriptionContainer.layout(true); + return; + } + } + mDescriptionLabel.setText(""); //$NON-NLS1-$ + } + + + // End of hiding from SWT Designer + //$hide<<$ + +} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/InstalledPackagesPage.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/InstalledPackagesPage.java new file mode 100755 index 0000000..118760c --- /dev/null +++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/InstalledPackagesPage.java @@ -0,0 +1,200 @@ +/* + * 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.sdkuilib.internal.repository; + +import com.android.sdklib.internal.repository.ITask; +import com.android.sdklib.internal.repository.ITaskMonitor; + +import org.eclipse.jface.viewers.TableViewer; +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.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +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 + * - delete callback + * - refresh callback + */ + +public class InstalledPackagesPage extends Composite { + private UpdaterData mUpdaterData; + + private Label mSdkLocLabel; + private Text mSdkLocText; + private Button mSdkLocBrowse; + private Label mInstalledPkgLabel; + private TableViewer mTableViewerInstPkg; + private Table mTableInstPkg; + private TableColumn mColumnInstSummary; + private TableColumn mColumnInstApiLevel; + private TableColumn mColumnInstRevision; + private Group mDescriptionContainer; + private Composite mInstButtons; + private Button mInstUpdate; + private Label mPlaceholder1; + private Button mInstDelete; + private Label mPlaceholder2; + private Button mInstHomePage; + private Label mDescriptionLabel; + + /** + * Create the composite. + * @param parent The parent of the composite. + * @param updaterData An instance of {@link UpdaterData}. If null, a local + * one will be allocated just to help with the SWT Designer. + */ + public InstalledPackagesPage(Composite parent, UpdaterData updaterData) { + super(parent, SWT.BORDER); + + mUpdaterData = updaterData != null ? updaterData : new UpdaterData(); + + createContents(this); + } + + private void createContents(Composite parent) { + parent.setLayout(new GridLayout(3, false)); + + createSdkLocation(parent); + + mInstalledPkgLabel = new Label(parent, SWT.NONE); + mInstalledPkgLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 3, 1)); + mInstalledPkgLabel.setText("Installed Packages:"); + + mTableViewerInstPkg = new TableViewer(parent, SWT.BORDER | SWT.FULL_SELECTION); + mTableInstPkg = mTableViewerInstPkg.getTable(); + mTableInstPkg.setHeaderVisible(true); + mTableInstPkg.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1)); + + mColumnInstSummary = new TableColumn(mTableInstPkg, SWT.NONE); + mColumnInstSummary.setWidth(377); + mColumnInstSummary.setText("Summary"); + + mColumnInstApiLevel = new TableColumn(mTableInstPkg, SWT.NONE); + mColumnInstApiLevel.setWidth(100); + mColumnInstApiLevel.setText("API Level"); + + mColumnInstRevision = new TableColumn(mTableInstPkg, SWT.NONE); + mColumnInstRevision.setWidth(100); + mColumnInstRevision.setText("Revision"); + + mDescriptionContainer = new Group(parent, SWT.NONE); + mDescriptionContainer.setLayout(new GridLayout(1, false)); + mDescriptionContainer.setText("Description"); + mDescriptionContainer.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 3, 1)); + + mDescriptionLabel = new Label(mDescriptionContainer, SWT.NONE); + mDescriptionLabel.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, true, 1, 1)); + mDescriptionLabel.setText("Line1\nLine2\nLine3"); + + mInstButtons = new Composite(parent, SWT.NONE); + mInstButtons.setLayout(new GridLayout(5, false)); + mInstButtons.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(); //$hide$ (hide from SWT designer) + } + }); + mInstUpdate.setText("Update..."); + + mPlaceholder1 = new Label(mInstButtons, SWT.NONE); + mPlaceholder1.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..."); + + mPlaceholder2 = new Label(mInstButtons, SWT.NONE); + mPlaceholder2.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..."); + } + + private void createSdkLocation(Composite parent) { + mSdkLocLabel = new Label(parent, SWT.NONE); + mSdkLocLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); + mSdkLocLabel.setText("SDK Location:"); + + // If the sdk path is not user-customizable, do not create + // the browse button and use horizSpan=2 on the text field. + + mSdkLocText = new Text(parent, SWT.BORDER); + mSdkLocText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); + + if (mUpdaterData.canUserChangeSdkRoot()) { + mSdkLocBrowse = new Button(parent, SWT.NONE); + mSdkLocBrowse.setText("Browse..."); + } else { + mSdkLocText.setEditable(false); + ((GridData)mSdkLocText.getLayoutData()).horizontalSpan++; + } + + if (mUpdaterData.getOsSdkRoot() != null) { + mSdkLocText.setText(mUpdaterData.getOsSdkRoot()); + } + } + + @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>>$ + + protected void onUpdateInstalledPackage() { + ProgressTask.start(getShell(), "Test", new ITask() { + public void run(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) { + } + } + } + }); + } + + // End of hiding from SWT Designer + //$hide<<$ +} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ProgressTask.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ProgressTask.java new file mode 100755 index 0000000..3897096 --- /dev/null +++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ProgressTask.java @@ -0,0 +1,251 @@ +/* + * 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.sdkuilib.internal.repository; + +import com.android.sdklib.internal.repository.ITask; +import com.android.sdklib.internal.repository.ITaskMonitor; + +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; + +/* + * TODO: + * - trap window.close and treat it as a cancel request + * - on cancel as been clicked *and* the task finished,, change it to a "close" button + */ + + +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(); + } + } + + mCancelRequested = true; + + 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>>$ + + private ITask 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, ITask 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; + if (!mDialogShell.isDisposed()) { + 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) { + if (!mDialogShell.isDisposed()) { + 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) { + if (!mDialogShell.isDisposed()) { + 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(ITask task) { + mTask = task; + } + + /** + * Starts the task from {@link #setTask(ITask)} 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.run(ProgressTask.this); + if (mAutomaticallyCloseOnTaskCompletion) { + mCloseRequested = true; + } + } + }.start(); + } + } + + // End of hiding from SWT Designer + //$hide<<$ +} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ProgressTaskFactory.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ProgressTaskFactory.java new file mode 100755 index 0000000..ceb701e --- /dev/null +++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ProgressTaskFactory.java @@ -0,0 +1,39 @@ +/* + * 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.sdkuilib.internal.repository; + +import com.android.sdklib.internal.repository.ITask; +import com.android.sdklib.internal.repository.ITaskFactory; + +import org.eclipse.swt.widgets.Shell; + +/** + * An {@link ITaskFactory} that creates a new {@link ProgressTask} dialog + * for each new task. + */ +public class ProgressTaskFactory implements ITaskFactory { + + private final Shell mShell; + + public ProgressTaskFactory(Shell shell) { + mShell = shell; + } + + public void start(String title, ITask task) { + ProgressTask.start(mShell, title, task); + } +} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/RepoSources.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/RepoSources.java new file mode 100755 index 0000000..42ab5b2 --- /dev/null +++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/RepoSources.java @@ -0,0 +1,155 @@ +/* + * 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.sdkuilib.internal.repository; + +import com.android.sdklib.internal.repository.IDescription; +import com.android.sdklib.internal.repository.ITaskFactory; +import com.android.sdklib.internal.repository.RepoSource; + +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 java.util.ArrayList; + +/** + * A list of sdk-repository sources. + * + * This implementation is UI dependent. + */ +class RepoSources { + + private ArrayList mSources = new ArrayList(); + private ITaskFactory mTaskFactory; + + public RepoSources() { + } + + public void setTaskFactory(ITaskFactory taskFactory) { + mTaskFactory = taskFactory; + } + + 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) { + if (element instanceof IDescription) { + return ((IDescription) element).getShortDescription(); + } + 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(mTaskFactory); + 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/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterData.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterData.java new file mode 100755 index 0000000..920769b --- /dev/null +++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterData.java @@ -0,0 +1,51 @@ +/* + * 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.sdkuilib.internal.repository; + +/** + * Data shared between {@link UpdaterWindowImpl} and its pages. + */ +class UpdaterData { + private String mOsSdkRoot; + private boolean mUserCanChangeSdkRoot; + private RepoSources mSources = new RepoSources(); + + public void setOsSdkRoot(String osSdkRoot) { + mOsSdkRoot = osSdkRoot; + } + + public String getOsSdkRoot() { + return mOsSdkRoot; + } + + public void setUserCanChangeSdkRoot(boolean userCanChangeSdkRoot) { + mUserCanChangeSdkRoot = userCanChangeSdkRoot; + } + + public boolean canUserChangeSdkRoot() { + return mUserCanChangeSdkRoot; + } + + public void setSources(RepoSources sources) { + mSources = sources; + } + + public RepoSources getSources() { + return mSources; + } + +} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterWindowImpl.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterWindowImpl.java new file mode 100755 index 0000000..50ebdb6 --- /dev/null +++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterWindowImpl.java @@ -0,0 +1,223 @@ +/* + * 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.sdkuilib.internal.repository; + + +import com.android.sdklib.internal.repository.RepoSource; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.custom.SashForm; +import org.eclipse.swt.custom.StackLayout; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.ImageData; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.List; +import org.eclipse.swt.widgets.Shell; + +import java.io.InputStream; +import java.util.ArrayList; + +/** + * This is the private implementation of the UpdateWindow. + */ +public class UpdaterWindowImpl { + + private final UpdaterData mUpdaterData = new UpdaterData(); + private ArrayList mPages = new ArrayList(); + private boolean mInternalPageChange; + + // --- UI members --- + + protected Shell mAndroidSdkUpdater; + private SashForm mSashForm; + private List mPageList; + private Composite mPagesRootComposite; + private InstalledPackagesPage mInstalledPackagePage; + private AvailablePackagesPage mAvailablePackagesPage; + private StackLayout mStackLayout; + private Image mIconImage; + + public UpdaterWindowImpl(String osSdkRoot, boolean userCanChangeSdkRoot) { + mUpdaterData.setOsSdkRoot(osSdkRoot); + mUpdaterData.setUserCanChangeSdkRoot(userCanChangeSdkRoot); + } + + /** + * Open the window. + * @wbp.parser.entryPoint + */ + public void open() { + Display display = Display.getDefault(); + createContents(); + mAndroidSdkUpdater.open(); + mAndroidSdkUpdater.layout(); + + firstInit(); //$hide$ (hide from SWT designer) + + while (!mAndroidSdkUpdater.isDisposed()) { + if (!display.readAndDispatch()) { + display.sleep(); + } + } + } + + /** + * Create contents of the window. + */ + protected void createContents() { + mAndroidSdkUpdater = new Shell(); + setWindowImage(mAndroidSdkUpdater); + mAndroidSdkUpdater.addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + onAndroidSdkUpdaterDispose(); //$hide$ (hide from SWT designer) + } + }); + + mAndroidSdkUpdater.setLayout(new FillLayout(SWT.HORIZONTAL)); + mAndroidSdkUpdater.setMinimumSize(new Point(200, 50)); + mAndroidSdkUpdater.setSize(745, 433); + mAndroidSdkUpdater.setText("Android SDK Updater"); + + mSashForm = new SashForm(mAndroidSdkUpdater, SWT.NONE); + + mPageList = new List(mSashForm, SWT.BORDER); + mPageList.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + onPageListSelected(); //$hide$ (hide from SWT designer) + } + }); + + mPagesRootComposite = new Composite(mSashForm, SWT.NONE); + mStackLayout = new StackLayout(); + mPagesRootComposite.setLayout(mStackLayout); + + mInstalledPackagePage = new InstalledPackagesPage(mPagesRootComposite, mUpdaterData); + mAvailablePackagesPage = new AvailablePackagesPage(mPagesRootComposite, mUpdaterData); + mSashForm.setWeights(new int[] {150, 576}); + } + + + // -- Start of internal part ---------- + // Hide everything down-below from SWT designer + //$hide>>$ + + // --- UI Callbacks ----------- + + private void onAndroidSdkUpdaterDispose() { + if (mIconImage != null) { + mIconImage.dispose(); + mIconImage = null; + } + } + + private void setWindowImage(Shell androidSdkUpdater) { + InputStream stream = getClass().getResourceAsStream("android_icon_16.png"); //$NON-NLS-1$ + if (stream != null) { + try { + ImageData imgData = new ImageData(stream); + mIconImage = new Image(mAndroidSdkUpdater.getDisplay(), + imgData, + imgData.getTransparencyMask()); + mAndroidSdkUpdater.setImage(mIconImage); + } catch (SWTException e) { + // ignore + } catch (IllegalArgumentException e) { + // ignore + } + } + } + + private Shell getShell() { + return mAndroidSdkUpdater; + } + + /** + * Once the UI has been created, initialize the content + */ + private void firstInit() { + addPage(mInstalledPackagePage, "Installed Packages"); + addPage(mAvailablePackagesPage, "Available Packages"); + displayPage(0); + mPageList.setSelection(0); + + setupSources(); + scanLocalSdkFolders(); + } + + // --- page switching --- + + private void addPage(Composite page, String title) { + page.setData(title); + mPages.add(page); + mPageList.add(title); + } + + private void onPageListSelected() { + if (mInternalPageChange == false) { + int index = mPageList.getSelectionIndex(); + if (index >= 0) { + displayPage(index); + } + } + } + + private void displayPage(int index) { + Composite page = mPages.get(index); + if (page != null) { + mStackLayout.topControl = page; + mPagesRootComposite.layout(true); + + if (!mInternalPageChange) { + mInternalPageChange = true; + mPageList.setSelection(index); + mInternalPageChange = false; + } + } + } + + private void setupSources() { + mUpdaterData.getSources().setTaskFactory(new ProgressTaskFactory(getShell())); + + mUpdaterData.getSources().add(new RepoSource( + "https://dl.google.com/android/eclipse/repository/index.xml", //$NON-NLS-1$ + false /* addonOnly */)); + + String url = System.getenv("TEMP_SDK_URL"); // TODO STOPSHIP temporary remove before shipping + if (url != null) { + mUpdaterData.getSources().add(new RepoSource(url, false /* addonOnly */)); + } + + mAvailablePackagesPage.setInput(mUpdaterData.getSources()); + } + + private void scanLocalSdkFolders() { + // TODO Auto-generated method stub + + } + + // End of hiding from SWT Designer + //$hide<<$ +} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/android_icon_16.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/android_icon_16.png new file mode 100755 index 0000000..0b0744b Binary files /dev/null and b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/android_icon_16.png differ diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/AvailablePackagesPage.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/AvailablePackagesPage.java deleted file mode 100755 index 7c4565a..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/AvailablePackagesPage.java +++ /dev/null @@ -1,116 +0,0 @@ -package com.android.sdkuilib.repository; - -import com.android.sdkuilib.repository.UpdaterWindow.UpdaterData; - -import org.eclipse.jface.viewers.CheckboxTreeViewer; -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.Tree; -import org.eclipse.swt.widgets.TreeColumn; - -class AvailablePackagesPage extends Composite { - - private final UpdaterData mUpdaterData; - - private CheckboxTreeViewer mTreeViewAvailPkg; - private Tree mTreeAvailPkg; - private TreeColumn mColumnAvailSummary; - private TreeColumn mColumnAvailApiLevel; - private TreeColumn mColumnAvailRevision; - private TreeColumn mColumnAvailOs; - private TreeColumn mColumnAvailInstalled; - private Group mAvailDescription; - private Button mAvailAddSite; - private Button mAvailRemoveSite; - private Label mPlaceholder3; - private Button mAvailRefresh; - private Button mAvailInstallSelected; - - - /** - * Create the composite. - * @param parent The parent of the composite. - * @param updaterData An instance of {@link UpdaterWindow.UpdaterData}. If null, a local - * one will be allocated just to help with the SWT Designer. - */ - public AvailablePackagesPage(Composite parent, UpdaterData updaterData) { - super(parent, SWT.BORDER); - - mUpdaterData = updaterData != null ? updaterData : new UpdaterWindow.UpdaterData(); - - createContents(this); - } - - private void createContents(Composite parent) { - parent.setLayout(new GridLayout(5, false)); - - mTreeViewAvailPkg = new CheckboxTreeViewer(parent, SWT.BORDER); - mTreeViewAvailPkg.setContentProvider(mUpdaterData.getSources().getContentProvider()); - mTreeViewAvailPkg.setLabelProvider(mUpdaterData.getSources().getLabelProvider()); - mTreeAvailPkg = mTreeViewAvailPkg.getTree(); - mTreeAvailPkg.setHeaderVisible(true); - mTreeAvailPkg.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 5, 1)); - - mColumnAvailSummary = new TreeColumn(mTreeAvailPkg, SWT.NONE); - mColumnAvailSummary.setWidth(289); - mColumnAvailSummary.setText("Summary"); - - mColumnAvailApiLevel = new TreeColumn(mTreeAvailPkg, SWT.NONE); - mColumnAvailApiLevel.setWidth(66); - mColumnAvailApiLevel.setText("API Level"); - - mColumnAvailRevision = new TreeColumn(mTreeAvailPkg, SWT.NONE); - mColumnAvailRevision.setWidth(63); - mColumnAvailRevision.setText("Revision"); - - mColumnAvailOs = new TreeColumn(mTreeAvailPkg, SWT.NONE); - mColumnAvailOs.setWidth(100); - mColumnAvailOs.setText("OS/Arch"); - - mColumnAvailInstalled = new TreeColumn(mTreeAvailPkg, SWT.NONE); - mColumnAvailInstalled.setWidth(59); - mColumnAvailInstalled.setText("Installed"); - - mAvailDescription = new Group(parent, SWT.NONE); - mAvailDescription.setText("Description"); - mAvailDescription.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 5, 1)); - - mAvailAddSite = new Button(parent, SWT.NONE); - mAvailAddSite.setText("Add Site..."); - - mAvailRemoveSite = new Button(parent, SWT.NONE); - mAvailRemoveSite.setText("Delete Site..."); - - mPlaceholder3 = new Label(parent, SWT.NONE); - mPlaceholder3.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, false, 1, 1)); - - mAvailRefresh = new Button(parent, SWT.NONE); - mAvailRefresh.setText("Refresh"); - - mAvailInstallSelected = new Button(parent, SWT.NONE); - mAvailInstallSelected.setText("Install Selected"); - } - - @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>>$ - - public void setInput(RepoSources sources) { - mTreeViewAvailPkg.setInput(sources); - } - - - // End of hiding from SWT Designer - //$hide<<$ - -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/ITaskMonitor.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/ITaskMonitor.java deleted file mode 100755 index 72375ab..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/ITaskMonitor.java +++ /dev/null @@ -1,60 +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.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/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/InstalledPackagesPage.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/InstalledPackagesPage.java deleted file mode 100755 index 95d180d..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/InstalledPackagesPage.java +++ /dev/null @@ -1,168 +0,0 @@ -package com.android.sdkuilib.repository; - -import com.android.sdkuilib.repository.ProgressTask.ThreadTask; -import com.android.sdkuilib.repository.UpdaterWindow.UpdaterData; - -import org.eclipse.jface.viewers.TableViewer; -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.Group; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Table; -import org.eclipse.swt.widgets.TableColumn; -import org.eclipse.swt.widgets.Text; - -public class InstalledPackagesPage extends Composite { - private UpdaterData mUpdaterData; - - private Label mSdkLocLabel; - private Text mSdkLocText; - private Button mSdkLocBrowse; - private Label mInstalledPkgLabel; - private TableViewer mTableViewerInstPkg; - private Table mTableInstPkg; - private TableColumn mColumnInstSummary; - private TableColumn mColumnInstApiLevel; - private TableColumn mColumnInstRevision; - private Group mInstDescription; - private Composite mInstButtons; - private Button mInstUpdate; - private Label mPlaceholder1; - private Button mInstDelete; - private Label mPlaceholder2; - private Button mInstHomePage; - - /** - * Create the composite. - * @param parent The parent of the composite. - * @param updaterData An instance of {@link UpdaterWindow.UpdaterData}. If null, a local - * one will be allocated just to help with the SWT Designer. - */ - public InstalledPackagesPage(Composite parent, UpdaterData updaterData) { - super(parent, SWT.BORDER); - - mUpdaterData = updaterData != null ? updaterData : new UpdaterWindow.UpdaterData(); - - createContents(this); - } - - private void createContents(Composite parent) { - parent.setLayout(new GridLayout(3, false)); - - createSdkLocation(parent); - - mInstalledPkgLabel = new Label(parent, SWT.NONE); - mInstalledPkgLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 3, 1)); - mInstalledPkgLabel.setText("Installed Packages:"); - - mTableViewerInstPkg = new TableViewer(parent, SWT.BORDER | SWT.FULL_SELECTION); - mTableInstPkg = mTableViewerInstPkg.getTable(); - mTableInstPkg.setHeaderVisible(true); - mTableInstPkg.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1)); - - mColumnInstSummary = new TableColumn(mTableInstPkg, SWT.NONE); - mColumnInstSummary.setWidth(377); - mColumnInstSummary.setText("Summary"); - - mColumnInstApiLevel = new TableColumn(mTableInstPkg, SWT.NONE); - mColumnInstApiLevel.setWidth(100); - mColumnInstApiLevel.setText("API Level"); - - mColumnInstRevision = new TableColumn(mTableInstPkg, SWT.NONE); - mColumnInstRevision.setWidth(100); - mColumnInstRevision.setText("Revision"); - - mInstDescription = new Group(parent, SWT.NONE); - mInstDescription.setText("Description"); - mInstDescription.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 3, 1)); - - mInstButtons = new Composite(parent, SWT.NONE); - mInstButtons.setLayout(new GridLayout(5, false)); - mInstButtons.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(); //$hide$ (hide from SWT designer) - } - }); - mInstUpdate.setText("Update..."); - - mPlaceholder1 = new Label(mInstButtons, SWT.NONE); - mPlaceholder1.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..."); - - mPlaceholder2 = new Label(mInstButtons, SWT.NONE); - mPlaceholder2.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..."); - } - - private void createSdkLocation(Composite parent) { - mSdkLocLabel = new Label(parent, SWT.NONE); - mSdkLocLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); - mSdkLocLabel.setText("SDK Location:"); - - // If the sdk path is not user-customizable, do not create - // the browse button and use horizSpan=2 on the text field. - - mSdkLocText = new Text(parent, SWT.BORDER); - mSdkLocText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); - - if (mUpdaterData.canUserChangeSdkRoot()) { - mSdkLocBrowse = new Button(parent, SWT.NONE); - mSdkLocBrowse.setText("Browse..."); - } else { - mSdkLocText.setEditable(false); - ((GridData)mSdkLocText.getLayoutData()).horizontalSpan++; - } - - if (mUpdaterData.getOsSdkRoot() != null) { - mSdkLocText.setText(mUpdaterData.getOsSdkRoot()); - } - } - - @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>>$ - - 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) { - } - } - } - }); - } - - - // End of hiding from SWT Designer - //$hide<<$ -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/ProgressTask.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/ProgressTask.java deleted file mode 100755 index ee768dd..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/ProgressTask.java +++ /dev/null @@ -1,236 +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.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(); - } - } - - // End of hiding from SWT Designer - //$hide<<$ -} diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/RepoSource.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/RepoSource.java deleted file mode 100755 index d2f65de..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/RepoSource.java +++ /dev/null @@ -1,316 +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.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/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/RepoSources.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/RepoSources.java deleted file mode 100755 index c06e16d..0000000 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/RepoSources.java +++ /dev/null @@ -1,147 +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.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/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/UpdaterWindow.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/UpdaterWindow.java index a9f5cdd..0d067ae 100755 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/UpdaterWindow.java +++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/UpdaterWindow.java @@ -1,11 +1,11 @@ /* * Copyright (C) 2009 The Android Open Source Project * - * Licensed under the Eclipse Public License, Version 1.0 (the "License"); + * 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.eclipse.org/org/documents/epl-v10.php + * 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, @@ -16,230 +16,31 @@ package com.android.sdkuilib.repository; -import org.eclipse.swt.SWT; -import org.eclipse.swt.SWTException; -import org.eclipse.swt.custom.SashForm; -import org.eclipse.swt.custom.StackLayout; -import org.eclipse.swt.events.DisposeEvent; -import org.eclipse.swt.events.DisposeListener; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.graphics.ImageData; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.layout.FillLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.List; -import org.eclipse.swt.widgets.Shell; - -import java.io.InputStream; -import java.util.ArrayList; +import com.android.sdkuilib.internal.repository.UpdaterWindowImpl; +/** + * Opens an SDK Updater Window. + * + * This is the public interface for using the window. + */ public class UpdaterWindow { - static class UpdaterData { - private String mOsSdkRoot; - private boolean mUserCanChangeSdkRoot; - private RepoSources mSources = new RepoSources(); - - public void setOsSdkRoot(String osSdkRoot) { - mOsSdkRoot = osSdkRoot; - } - - public String getOsSdkRoot() { - return mOsSdkRoot; - } - - public void setUserCanChangeSdkRoot(boolean userCanChangeSdkRoot) { - mUserCanChangeSdkRoot = userCanChangeSdkRoot; - } - - public boolean canUserChangeSdkRoot() { - return mUserCanChangeSdkRoot; - } - - public void setSources(RepoSources sources) { - mSources = sources; - } - - public RepoSources getSources() { - return mSources; - } - } - - private final UpdaterData mUpdaterData = new UpdaterData(); - private ArrayList mPages = new ArrayList(); - private boolean mInternalPageChange; - - // --- UI members --- - - protected Shell mAndroidSdkUpdater; - private SashForm mSashForm; - private List mPageList; - private Composite mPagesRootComposite; - private InstalledPackagesPage mInstalledPackagePage; - private AvailablePackagesPage mAvailablePackagesPage; - private StackLayout mStackLayout; - private Image mIconImage; - - public UpdaterWindow(String osSdkRoot, boolean userCanChangeSdkRoot) { - mUpdaterData.setOsSdkRoot(osSdkRoot); - mUpdaterData.setUserCanChangeSdkRoot(userCanChangeSdkRoot); - } - - /** - * Open the window. - * @wbp.parser.entryPoint - */ - public void open() { - Display display = Display.getDefault(); - createContents(); - mAndroidSdkUpdater.open(); - mAndroidSdkUpdater.layout(); - - firstInit(); //$hide$ (hide from SWT designer) - - while (!mAndroidSdkUpdater.isDisposed()) { - if (!display.readAndDispatch()) { - display.sleep(); - } - } - } + private UpdaterWindowImpl mWindow; /** - * Create contents of the window. + * Creates a new window. Caller must call open(), which will block. + * @param osSdkRoot The OS path to the SDK root. + * @param userCanChangeSdkRoot If true, the window lets the user change the SDK path + * being browsed. */ - protected void createContents() { - mAndroidSdkUpdater = new Shell(); - setWindowImage(mAndroidSdkUpdater); - mAndroidSdkUpdater.addDisposeListener(new DisposeListener() { - public void widgetDisposed(DisposeEvent e) { - onAndroidSdkUpdaterDispose(); //$hide$ (hide from SWT designer) - } - }); - - mAndroidSdkUpdater.setLayout(new FillLayout(SWT.HORIZONTAL)); - mAndroidSdkUpdater.setMinimumSize(new Point(200, 50)); - mAndroidSdkUpdater.setSize(745, 433); - mAndroidSdkUpdater.setText("Android SDK Updater"); - - mSashForm = new SashForm(mAndroidSdkUpdater, SWT.NONE); - - mPageList = new List(mSashForm, SWT.BORDER); - mPageList.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - onPageListSelected(e); //$hide$ (hide from SWT designer) - } - }); - - mPagesRootComposite = new Composite(mSashForm, SWT.NONE); - mStackLayout = new StackLayout(); - mPagesRootComposite.setLayout(mStackLayout); - - mInstalledPackagePage = new InstalledPackagesPage(mPagesRootComposite, mUpdaterData); - mAvailablePackagesPage = new AvailablePackagesPage(mPagesRootComposite, mUpdaterData); - mSashForm.setWeights(new int[] {150, 576}); - } - - - // -- Start of internal part ---------- - // Hide everything down-below from SWT designer - //$hide>>$ - - // --- UI Callbacks ----------- - - private void onAndroidSdkUpdaterDispose() { - if (mIconImage != null) { - mIconImage.dispose(); - mIconImage = null; - } - } - - private void setWindowImage(Shell androidSdkUpdater) { - InputStream stream = getClass().getResourceAsStream("android_icon_16.png"); //$NON-NLS-1$ - if (stream != null) { - try { - ImageData imgData = new ImageData(stream); - mIconImage = new Image(mAndroidSdkUpdater.getDisplay(), - imgData, - imgData.getTransparencyMask()); - mAndroidSdkUpdater.setImage(mIconImage); - } catch (SWTException e) { - // ignore - } catch (IllegalArgumentException e) { - // ignore - } - } - } - - private Shell getShell() { - return mAndroidSdkUpdater; + public UpdaterWindow(String osSdkRoot, boolean userCanChangeSdkRoot) { + mWindow = new UpdaterWindowImpl(osSdkRoot, userCanChangeSdkRoot); } /** - * Once the UI has been created, initialize the content + * Opens the window. */ - private void firstInit() { - addPage(mInstalledPackagePage, "Installed Packages"); - addPage(mAvailablePackagesPage, "Available Packages"); - displayPage(0); - mPageList.setSelection(0); - - setupSources(); - scanLocalSdkFolders(); - } - - // --- page switching --- - - private void addPage(Composite page, String title) { - page.setData(title); - mPages.add(page); - mPageList.add(title); - } - - private void onPageListSelected(SelectionEvent e) { - if (mInternalPageChange == false) { - int index = mPageList.getSelectionIndex(); - if (index >= 0) { - displayPage(index); - } - } - } - - private void displayPage(int index) { - Composite page = mPages.get(index); - if (page != null) { - mStackLayout.topControl = page; - mPagesRootComposite.layout(true); - - if (!mInternalPageChange) { - mInternalPageChange = true; - mPageList.setSelection(index); - mInternalPageChange = false; - } - } - } - - private void setupSources() { - mUpdaterData.getSources().setShell(getShell()); - - mUpdaterData.getSources().add(new RepoSource( - "https://dl.google.com/android/eclipse/repository/index.xml", //$NON-NLS-1$ - false /* addonOnly */)); - mUpdaterData.getSources().add(new RepoSource( - "http://www.corp.google.com/~raphael/android/sdk-repo/repository.xml", //$NON-NLS-1$ - false /* addonOnly */)); - - mAvailablePackagesPage.setInput(mUpdaterData.getSources()); - } - - private void scanLocalSdkFolders() { - // TODO Auto-generated method stub - + public void open() { + mWindow.open(); } - - // End of hiding from SWT Designer - //$hide<<$ } diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/android_icon_16.png b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/android_icon_16.png deleted file mode 100755 index 0b0744b..0000000 Binary files a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/repository/android_icon_16.png and /dev/null differ -- cgit v1.1