aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ddms/app/.classpath2
-rw-r--r--ddms/app/Android.mk1
-rw-r--r--ddms/app/README78
-rw-r--r--ddms/app/etc/manifest.txt2
-rw-r--r--ddms/app/src/com/android/ddms/PrefsDialog.java6
-rw-r--r--ddms/app/src/com/android/ddms/UIThread.java154
-rw-r--r--ddms/libs/ddmuilib/src/com/android/ddmuilib/ImageLoader.java9
-rw-r--r--draw9patch/src/com/android/draw9patch/ui/MainFrame.java7
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/icons/requestFocus.pngbin0 -> 528 bytes
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/EditTextRule.java120
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/LayoutConstants.java4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/descriptors/DescriptorsUtils.java7
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors/LayoutDescriptors.java38
-rwxr-xr-xeclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/PaletteControl.java16
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/extra-view-metadata.xml3
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/AndroidLaunchController.java3
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/DeviceChooserDialog.java2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/EmulatorConfigTab.java2
-rwxr-xr-xeclipse/scripts/create_ddms_symlinks.sh7
-rwxr-xr-xeclipse/scripts/create_hierarchyviewer_symlinks.sh7
-rw-r--r--hierarchyviewer2/app/.classpath1
-rw-r--r--hierarchyviewer2/app/Android.mk3
-rwxr-xr-xhierarchyviewer2/app/README69
-rw-r--r--hierarchyviewer2/app/src/com/android/hierarchyviewer/AboutDialog.java4
-rw-r--r--hierarchyviewer2/app/src/com/android/hierarchyviewer/HierarchyViewerApplication.java73
-rw-r--r--hierarchyviewer2/app/src/com/android/hierarchyviewer/actions/AboutAction.java2
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/Android.mk2
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/images/auto-refresh.png (renamed from hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/auto-refresh.png)bin541 -> 541 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/images/capture-psd.png (renamed from hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/capture-psd.png)bin339 -> 339 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/images/device-view-selected.png (renamed from hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/device-view-selected.png)bin254 -> 254 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/images/device-view.png (renamed from hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/device-view.png)bin228 -> 228 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/images/display.png (renamed from hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/display.png)bin946 -> 946 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/images/filtered.png (renamed from hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/filtered.png)bin9242 -> 9242 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/images/green.png (renamed from hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/green.png)bin302 -> 302 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/images/inspect-screenshot.png (renamed from hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/inspect-screenshot.png)bin412 -> 412 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/images/invalidate.png (renamed from hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/invalidate.png)bin391 -> 391 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/images/load-all-views.png (renamed from hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/load-all-views.png)bin728 -> 728 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/images/load-overlay.png (renamed from hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/load-overlay.png)bin549 -> 549 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/images/load-view-hierarchy.png (renamed from hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/load-view-hierarchy.png)bin288 -> 288 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/images/not-selected.png (renamed from hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/not-selected.png)bin12468 -> 12468 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/images/on-black.png (renamed from hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/on-black.png)bin157 -> 157 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/images/on-white.png (renamed from hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/on-white.png)bin158 -> 158 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/images/pixel-perfect-view-selected.png (renamed from hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/pixel-perfect-view-selected.png)bin734 -> 734 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/images/pixel-perfect-view.png (renamed from hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/pixel-perfect-view.png)bin733 -> 733 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/images/red.png (renamed from hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/red.png)bin383 -> 383 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/images/refresh-windows.png (renamed from hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/refresh-windows.png)bin872 -> 872 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/images/request-layout.png (renamed from hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/request-layout.png)bin223 -> 223 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/images/save.png (renamed from hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/save.png)bin360 -> 360 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/images/sdk-hierarchyviewer-128.png (renamed from hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/sdk-hierarchyviewer-128.png)bin17512 -> 17512 bytes
-rwxr-xr-xhierarchyviewer2/libs/hierarchyviewerlib/src/images/sdk-hierarchyviewer-16.pngbin0 -> 880 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/images/selected-filtered-small.png (renamed from hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/selected-filtered-small.png)bin5182 -> 5182 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/images/selected-filtered.png (renamed from hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/selected-filtered.png)bin9015 -> 9015 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/images/selected-small.png (renamed from hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/selected-small.png)bin12611 -> 12611 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/images/selected.png (renamed from hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/selected.png)bin12159 -> 12159 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/images/show-extras.png (renamed from hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/show-extras.png)bin330 -> 330 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/images/show-overlay.png (renamed from hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/show-overlay.png)bin958 -> 958 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/images/tree-view-selected.png (renamed from hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/tree-view-selected.png)bin276 -> 276 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/images/tree-view.png (renamed from hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/tree-view.png)bin281 -> 281 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/images/yellow.png (renamed from hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/yellow.png)bin255 -> 255 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/about-small.jpgbin1578 -> 0 bytes
-rw-r--r--hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/about.jpgbin17237 -> 0 bytes
-rwxr-xr-xsdkmanager/app/etc/android4
-rwxr-xr-xsdkmanager/app/etc/android.bat2
-rw-r--r--sdkmanager/app/src/com/android/sdkmanager/Main.java47
-rw-r--r--sdkmanager/app/src/com/android/sdkmanager/SdkCommandLine.java230
-rw-r--r--sdkmanager/app/tests/com/android/sdkmanager/AvdManagerTest.java51
-rw-r--r--sdkmanager/app/tests/com/android/sdkmanager/MainTest.java65
-rwxr-xr-xsdkmanager/app/tests/com/android/sdkmanager/SdkManagerTestCase.java182
-rw-r--r--sdkmanager/app/tests/com/android/sdkmanager/SdkManagerTestUtil.java88
-rwxr-xr-xsdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdInfo.java334
-rw-r--r--sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java409
-rw-r--r--sdkmanager/libs/sdkuilib/.classpath2
-rw-r--r--sdkmanager/libs/sdkuilib/README8
-rwxr-xr-xsdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/AvdManagerPage.java3
-rwxr-xr-xsdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/PackagesPage.java226
-rwxr-xr-xsdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterWindowImpl2.java77
-rw-r--r--sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdCreationDialog.java4
-rw-r--r--sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdDetailsDialog.java6
-rw-r--r--sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdSelector.java4
-rw-r--r--sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdStartDialog.java2
-rw-r--r--swtmenubar/.classpath2
-rw-r--r--swtmenubar/Android.mk5
-rwxr-xr-xswtmenubar/README21
-rwxr-xr-xswtmenubar/src-darwin/com/android/menubar/internal/MenuBarEnhancerCarbon.java7
-rw-r--r--swtmenubar/src-darwin/com/android/menubar/internal/MenuBarEnhancerCocoa.java341
-rwxr-xr-xswtmenubar/src-darwin/com/android/menubar/internal/MenuBarEnhancerCocoa.java.txt334
-rw-r--r--swtmenubar/src/com/android/menubar/IMenuBarEnhancer.java33
-rw-r--r--swtmenubar/src/com/android/menubar/MenuBarEnhancer.java147
88 files changed, 2022 insertions, 1234 deletions
diff --git a/ddms/app/.classpath b/ddms/app/.classpath
index 3f01de4..6caf176 100644
--- a/ddms/app/.classpath
+++ b/ddms/app/.classpath
@@ -3,9 +3,11 @@
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/ANDROID_SWT"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/ANDROID_OSGI"/>
<classpathentry combineaccessrules="false" kind="src" path="/ddmlib"/>
<classpathentry combineaccessrules="false" kind="src" path="/ddmuilib"/>
<classpathentry combineaccessrules="false" kind="src" path="/AndroidPrefs"/>
<classpathentry combineaccessrules="false" kind="src" path="/SdkStatsService"/>
+ <classpathentry kind="var" path="ANDROID_OUT_FRAMEWORK/swtmenubar.jar" sourcepath="/ANDROID_SRC/sdk/swtmenubar/src"/>
<classpathentry kind="output" path="bin"/>
</classpath>
diff --git a/ddms/app/Android.mk b/ddms/app/Android.mk
index 6be32be..d1e4a52 100644
--- a/ddms/app/Android.mk
+++ b/ddms/app/Android.mk
@@ -17,6 +17,7 @@ LOCAL_JAVA_LIBRARIES := \
ddmlib \
ddmuilib \
swt \
+ swtmenubar \
org.eclipse.jface_3.4.2.M20090107-0800 \
org.eclipse.equinox.common_3.4.0.v20080421-2006 \
org.eclipse.core.commands_3.4.0.I20080509-2000
diff --git a/ddms/app/README b/ddms/app/README
index cc55ddd..42efb7b 100644
--- a/ddms/app/README
+++ b/ddms/app/README
@@ -1,11 +1,75 @@
-Using the Eclipse projects for ddms.
+Using the Eclipse project DDMS
+------------------------------
-ddms requires SWT to compile.
+DDMS requires some external libraries to compile.
+If you build DDMS using the makefile, you have nothing to configure.
+However if you want to develop on DDMS using Eclipse, you need to
+perform the following configuration.
-SWT is available in the depot under //device/prebuild/<platform>/swt
-Because the build path cannot contain relative path that are not inside the project directory,
-the .classpath file references a user library called ANDROID_SWT.
+-------
+1- Projects required in Eclipse
+-------
-In order to compile the project, make a user library called ANDROID_SWT containing the jar
-available at //device/prebuild/<platform>/swt. \ No newline at end of file
+To run DDMS from Eclipse, you need to import the following 5 projects:
+
+ - sdk/androidpprefs: project AndroidPrefs
+ - sdk/sdkstats: project SdkStatsService
+ - sdk/ddms/app: project Ddms
+ - sdk/ddms/libs/ddmlib: project Ddmlib
+ - sdk/ddms/libs/ddmuilib: project Ddmuilib
+
+
+-------
+2- DDMS requires some SWT and OSGI JARs to compile.
+-------
+
+SWT is available in the tree under prebuild/<platform>/swt
+
+Because the build path cannot contain relative path that are not inside
+the project directory, the .classpath file references a user library
+called ANDROID_SWT.
+SWT depends on OSGI, so we'll also create an ANDROID_OSGI library for that.
+
+In order to compile the project:
+- Open Preferences > Java > Build Path > User Libraries
+
+- Create a new user library named ANDROID_SWT
+- Add the following 4 JAR files:
+
+ - prebuilt/<platform>/swt/swt.jar
+ - prebuilt/common/eclipse/org.eclipse.core.commands_3.*.jar
+ - prebuilt/common/eclipse/org.eclipse.equinox.common_3.*.jar
+ - prebuilt/common/eclipse/org.eclipse.jface_3.*.jar
+
+- Create a new user library named ANDROID_OSGI
+- Add the following JAR file:
+
+ - prebuilt/common/osgi/osgi.jar
+
+
+-------
+3- DDMS also requires the compiled SwtMenuBar library.
+-------
+
+Build the swtmenubar library:
+$ cd $TOP (top of Android tree)
+$ . build/envsetup.sh && lunch sdk-eng
+$ sdk/eclipse/scripts/create_sdkman_symlinks.sh
+
+Define a classpath variable in Eclipse:
+- Open Preferences > Java > Build Path > Classpath Variables
+- Create a new classpath variable named ANDROID_OUT_FRAMEWORK
+- Set its folder value to <Android tree>/out/host/<platform>/framework
+- Create a new classpath variable named ANDROID_SRC
+- Set its folder value to <Android tree>
+
+You might need to clean the ddms project (Project > Clean...) after
+you add the new classpath variable, otherwise previous errors might not
+go away automatically.
+
+The ANDROID_SRC part should be optional. It allows you to have access to
+the SwtMenuBar generic parts from the Java editor.
+
+--
+EOF
diff --git a/ddms/app/etc/manifest.txt b/ddms/app/etc/manifest.txt
index e30c193..8c6ab23 100644
--- a/ddms/app/etc/manifest.txt
+++ b/ddms/app/etc/manifest.txt
@@ -1,3 +1,3 @@
Main-Class: com.android.ddms.Main
-Class-Path: androidprefs.jar sdkstats.jar ddmlib.jar ddmuilib.jar org.eclipse.jface_3.4.2.M20090107-0800.jar org.eclipse.equinox.common_3.4.0.v20080421-2006.jar org.eclipse.core.commands_3.4.0.I20080509-2000.jar jcommon-1.0.12.jar jfreechart-1.0.9.jar jfreechart-1.0.9-swt.jar osgi.jar
+Class-Path: androidprefs.jar sdkstats.jar ddmlib.jar ddmuilib.jar swtmenubar.jar org.eclipse.jface_3.4.2.M20090107-0800.jar org.eclipse.equinox.common_3.4.0.v20080421-2006.jar org.eclipse.core.commands_3.4.0.I20080509-2000.jar jcommon-1.0.12.jar jfreechart-1.0.9.jar jfreechart-1.0.9-swt.jar osgi.jar
diff --git a/ddms/app/src/com/android/ddms/PrefsDialog.java b/ddms/app/src/com/android/ddms/PrefsDialog.java
index 418b8ba..c957a89 100644
--- a/ddms/app/src/com/android/ddms/PrefsDialog.java
+++ b/ddms/app/src/com/android/ddms/PrefsDialog.java
@@ -294,7 +294,11 @@ public final class PrefsDialog {
dlg.setPreferenceStore(mPrefStore);
// run it
- dlg.open();
+ try {
+ dlg.open();
+ } catch (Throwable t) {
+ Log.e("ddms", t);
+ }
// save prefs
try {
diff --git a/ddms/app/src/com/android/ddms/UIThread.java b/ddms/app/src/com/android/ddms/UIThread.java
index 3304fff..cb6786a 100644
--- a/ddms/app/src/com/android/ddms/UIThread.java
+++ b/ddms/app/src/com/android/ddms/UIThread.java
@@ -50,6 +50,10 @@ import com.android.ddmuilib.logcat.LogColors;
import com.android.ddmuilib.logcat.LogFilter;
import com.android.ddmuilib.logcat.LogPanel;
import com.android.ddmuilib.logcat.LogPanel.ILogFilterStorageManager;
+import com.android.menubar.IMenuBarCallback;
+import com.android.menubar.IMenuBarEnhancer;
+import com.android.menubar.IMenuBarEnhancer.MenuBarMode;
+import com.android.menubar.MenuBarEnhancer;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.IPreferenceStore;
@@ -84,7 +88,6 @@ import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
-import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Sash;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TabFolder;
@@ -101,6 +104,8 @@ import java.util.ArrayList;
* when {@link IDevice} / {@link Client} selection changes.
*/
public class UIThread implements IUiSelectionListener, IClientChangeListener {
+ private static final String APP_NAME = "DDMS";
+
/*
* UI tab panel definitions. The constants here must match up with the array
* indices in mPanels. PANEL_CLIENT_LIST is a "virtual" panel representing
@@ -414,10 +419,10 @@ public class UIThread implements IUiSelectionListener, IClientChangeListener {
/**
* Create SWT objects and drive the user interface event loop.
- * @param location location of the folder that contains ddms.
+ * @param ddmsParentLocation location of the folder that contains ddms.
*/
public void runUI(String ddmsParentLocation) {
- Display.setAppName("ddms");
+ Display.setAppName(APP_NAME);
mDisplay = new Display();
final Shell shell = new Shell(mDisplay);
@@ -435,11 +440,11 @@ public class UIThread implements IUiSelectionListener, IClientChangeListener {
// dialog box only run in UI thread..
mDisplay.asyncExec(new Runnable() {
public void run() {
- Shell shell = mDisplay.getActiveShell();
+ Shell activeShell = mDisplay.getActiveShell();
if (logLevel == LogLevel.ERROR) {
- MessageDialog.openError(shell, tag, message);
+ MessageDialog.openError(activeShell, tag, message);
} else {
- MessageDialog.openWarning(shell, tag, message);
+ MessageDialog.openWarning(activeShell, tag, message);
}
}
});
@@ -556,20 +561,20 @@ public class UIThread implements IUiSelectionListener, IClientChangeListener {
shell.addControlListener(new ControlListener() {
public void controlMoved(ControlEvent e) {
// get the new x/y
- Rectangle rect = shell.getBounds();
+ Rectangle controlBounds = shell.getBounds();
// store in pref file
- PreferenceStore prefs = PrefsDialog.getStore();
- prefs.setValue(PrefsDialog.SHELL_X, rect.x);
- prefs.setValue(PrefsDialog.SHELL_Y, rect.y);
+ PreferenceStore currentPrefs = PrefsDialog.getStore();
+ currentPrefs.setValue(PrefsDialog.SHELL_X, controlBounds.x);
+ currentPrefs.setValue(PrefsDialog.SHELL_Y, controlBounds.y);
}
public void controlResized(ControlEvent e) {
// get the new w/h
- Rectangle rect = shell.getBounds();
+ Rectangle controlBounds = shell.getBounds();
// store in pref file
- PreferenceStore prefs = PrefsDialog.getStore();
- prefs.setValue(PrefsDialog.SHELL_WIDTH, rect.width);
- prefs.setValue(PrefsDialog.SHELL_HEIGHT, rect.height);
+ PreferenceStore currentPrefs = PrefsDialog.getStore();
+ currentPrefs.setValue(PrefsDialog.SHELL_WIDTH, controlBounds.width);
+ currentPrefs.setValue(PrefsDialog.SHELL_HEIGHT, controlBounds.height);
}
});
}
@@ -624,41 +629,31 @@ public class UIThread implements IUiSelectionListener, IClientChangeListener {
shell.addControlListener(new ControlListener() {
public void controlMoved(ControlEvent e) {
// get the new x/y
- Rectangle rect = shell.getBounds();
+ Rectangle controlBounds = shell.getBounds();
// store in pref file
- PreferenceStore prefs = PrefsDialog.getStore();
- prefs.setValue(PrefsDialog.EXPLORER_SHELL_X, rect.x);
- prefs.setValue(PrefsDialog.EXPLORER_SHELL_Y, rect.y);
+ PreferenceStore currentPrefs = PrefsDialog.getStore();
+ currentPrefs.setValue(PrefsDialog.EXPLORER_SHELL_X, controlBounds.x);
+ currentPrefs.setValue(PrefsDialog.EXPLORER_SHELL_Y, controlBounds.y);
}
public void controlResized(ControlEvent e) {
// get the new w/h
- Rectangle rect = shell.getBounds();
+ Rectangle controlBounds = shell.getBounds();
// store in pref file
- PreferenceStore prefs = PrefsDialog.getStore();
- prefs.setValue(PrefsDialog.EXPLORER_SHELL_WIDTH, rect.width);
- prefs.setValue(PrefsDialog.EXPLORER_SHELL_HEIGHT, rect.height);
+ PreferenceStore currentPrefs = PrefsDialog.getStore();
+ currentPrefs.setValue(PrefsDialog.EXPLORER_SHELL_WIDTH, controlBounds.width);
+ currentPrefs.setValue(PrefsDialog.EXPLORER_SHELL_HEIGHT, controlBounds.height);
}
});
}
/*
- * Set the confirm-before-close dialog. TODO: enable/disable in prefs. TODO:
- * is there any point in having this?
+ * Set the confirm-before-close dialog.
*/
private void setConfirmClose(final Shell shell) {
- if (true)
- return;
-
- shell.addListener(SWT.Close, new Listener() {
- public void handleEvent(Event event) {
- int style = SWT.APPLICATION_MODAL | SWT.YES | SWT.NO;
- MessageBox msgBox = new MessageBox(shell, style);
- msgBox.setText("Confirm...");
- msgBox.setMessage("Close DDM?");
- event.doit = (msgBox.open() == SWT.YES);
- }
- });
+ // Note: there was some commented out code to display a confirmation box
+ // when closing. The feature seems unnecessary and the code was not being
+ // used, so it has been removed.
}
/*
@@ -677,8 +672,6 @@ public class UIThread implements IUiSelectionListener, IClientChangeListener {
actionItem.setText("&Actions");
MenuItem deviceItem = new MenuItem(menuBar, SWT.CASCADE);
deviceItem.setText("&Device");
- MenuItem helpItem = new MenuItem(menuBar, SWT.CASCADE);
- helpItem.setText("&Help");
// create top-level menus
Menu fileMenu = new Menu(menuBar);
@@ -689,22 +682,11 @@ public class UIThread implements IUiSelectionListener, IClientChangeListener {
actionItem.setMenu(actionMenu);
Menu deviceMenu = new Menu(menuBar);
deviceItem.setMenu(deviceMenu);
- Menu helpMenu = new Menu(menuBar);
- helpItem.setMenu(helpMenu);
MenuItem item;
// create File menu items
item = new MenuItem(fileMenu, SWT.NONE);
- item.setText("&Preferences...");
- item.addSelectionListener(new SelectionAdapter() {
- @Override
- public void widgetSelected(SelectionEvent e) {
- PrefsDialog.run(shell);
- }
- });
-
- item = new MenuItem(fileMenu, SWT.NONE);
item.setText("&Static Port Configuration...");
item.addSelectionListener(new SelectionAdapter() {
@Override
@@ -714,18 +696,36 @@ public class UIThread implements IUiSelectionListener, IClientChangeListener {
}
});
- new MenuItem(fileMenu, SWT.SEPARATOR);
+ IMenuBarEnhancer enhancer = MenuBarEnhancer.setupMenu(APP_NAME, fileMenu,
+ new IMenuBarCallback() {
+ public void printError(String format, Object... args) {
+ Log.e("DDMS Menu Bar", String.format(format, args));
+ }
- item = new MenuItem(fileMenu, SWT.NONE);
- item.setText("E&xit\tCtrl-Q");
- item.setAccelerator('Q' | (Main.isMac() ? SWT.COMMAND : SWT.CONTROL));
- item.addSelectionListener(new SelectionAdapter() {
- @Override
- public void widgetSelected(SelectionEvent e) {
- shell.close();
+ public void onPreferencesMenuSelected() {
+ PrefsDialog.run(shell);
+ }
+
+ public void onAboutMenuSelected() {
+ AboutDialog dlg = new AboutDialog(shell);
+ dlg.open();
}
});
+ if (enhancer.getMenuBarMode() == MenuBarMode.GENERIC) {
+ new MenuItem(fileMenu, SWT.SEPARATOR);
+
+ item = new MenuItem(fileMenu, SWT.NONE);
+ item.setText("E&xit\tCtrl-Q");
+ item.setAccelerator('Q' | (Main.isMac() ? SWT.COMMAND : SWT.CONTROL));
+ item.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ shell.close();
+ }
+ });
+ }
+
// create edit menu items
mCopyMenuItem = new MenuItem(editMenu, SWT.NONE);
mCopyMenuItem.setText("&Copy\tCtrl-C");
@@ -900,32 +900,6 @@ public class UIThread implements IUiSelectionListener, IClientChangeListener {
}
});
- // create Help menu items
- item = new MenuItem(helpMenu, SWT.NONE);
- item.setText("&Contents...");
- item.addSelectionListener(new SelectionAdapter() {
- @Override
- public void widgetSelected(SelectionEvent e) {
- int style = SWT.APPLICATION_MODAL | SWT.OK;
- MessageBox msgBox = new MessageBox(shell, style);
- msgBox.setText("Help!");
- msgBox.setMessage("Help wanted.");
- msgBox.open();
- }
- });
-
- new MenuItem(helpMenu, SWT.SEPARATOR);
-
- item = new MenuItem(helpMenu, SWT.NONE);
- item.setText("&About...");
- item.addSelectionListener(new SelectionAdapter() {
- @Override
- public void widgetSelected(SelectionEvent e) {
- AboutDialog dlg = new AboutDialog(shell);
- dlg.open();
- }
- });
-
// tell the shell to use this menu
shell.setMenuBar(menuBar);
}
@@ -1007,7 +981,9 @@ public class UIThread implements IUiSelectionListener, IClientChangeListener {
e.y = Math.max(Math.min(e.y, bottom), 100);
if (e.y != sashRect.y) {
sashData.top = new FormAttachment(0, e.y);
- prefs.setValue(PREFERENCE_LOGSASH, e.y);
+ if (prefs != null) {
+ prefs.setValue(PREFERENCE_LOGSASH, e.y);
+ }
panelArea.layout();
}
}
@@ -1199,7 +1175,9 @@ public class UIThread implements IUiSelectionListener, IClientChangeListener {
e.x = Math.max(Math.min(e.x, right), minPanelWidth);
if (e.x != sashRect.x) {
sashData.left = new FormAttachment(0, e.x);
- prefs.setValue(PREFERENCE_SASH, e.x);
+ if (prefs != null) {
+ prefs.setValue(PREFERENCE_SASH, e.x);
+ }
comp.layout();
}
}
@@ -1282,13 +1260,13 @@ public class UIThread implements IUiSelectionListener, IClientChangeListener {
@Override
public void widgetSelected(SelectionEvent e) {
// disable the other actions and record current index
- for (int i = 0 ; i < mLogLevelActions.length; i++) {
- ToolItemAction a = mLogLevelActions[i];
+ for (int k = 0 ; k < mLogLevelActions.length; k++) {
+ ToolItemAction a = mLogLevelActions[k];
if (a == newAction) {
a.setChecked(true);
// set the log level
- mLogPanel.setCurrentFilterLogLevel(i+2);
+ mLogPanel.setCurrentFilterLogLevel(k+2);
} else {
a.setChecked(false);
}
diff --git a/ddms/libs/ddmuilib/src/com/android/ddmuilib/ImageLoader.java b/ddms/libs/ddmuilib/src/com/android/ddmuilib/ImageLoader.java
index 40cbd1d..fd480f6 100644
--- a/ddms/libs/ddmuilib/src/com/android/ddmuilib/ImageLoader.java
+++ b/ddms/libs/ddmuilib/src/com/android/ddmuilib/ImageLoader.java
@@ -140,13 +140,11 @@ public class ImageLoader {
if (imageStream != null) {
img = new Image(display, imageStream);
- if (img == null) {
- throw new NullPointerException("couldn't load " + tmp);
- }
-
mLoadedImages.put(filename, img);
+ }
- return img;
+ if (img == null) {
+ throw new RuntimeException("Failed to load " + tmp);
}
}
@@ -159,7 +157,6 @@ public class ImageLoader {
* Extra parameters allows for creation of a replacement image of the
* loading failed.
*
- * @param loader the image loader used.
* @param display the Display object
* @param fileName the file name
* @param width optional width to create replacement Image. If -1, null be
diff --git a/draw9patch/src/com/android/draw9patch/ui/MainFrame.java b/draw9patch/src/com/android/draw9patch/ui/MainFrame.java
index d5b6409..57f6cd9 100644
--- a/draw9patch/src/com/android/draw9patch/ui/MainFrame.java
+++ b/draw9patch/src/com/android/draw9patch/ui/MainFrame.java
@@ -40,9 +40,15 @@ public class MainFrame extends JFrame {
private JMenuItem saveMenuItem;
private ImageEditorPanel imageEditor;
+ private static final String TITLE_FORMAT = "Draw 9-patch: %s";
+
public MainFrame(String path) throws HeadlessException {
super("Draw 9-patch");
+ if (path != null) {
+ setTitle(String.format(TITLE_FORMAT, path));
+ }
+
buildActions();
buildMenuBar();
buildContent();
@@ -164,6 +170,7 @@ public class MainFrame extends JFrame {
protected void done() {
try {
showImageEditor(get(), file.getAbsolutePath());
+ setTitle(String.format(TITLE_FORMAT, file.getAbsolutePath()));
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/icons/requestFocus.png b/eclipse/plugins/com.android.ide.eclipse.adt/icons/requestFocus.png
new file mode 100644
index 0000000..205a032
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/icons/requestFocus.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/EditTextRule.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/EditTextRule.java
new file mode 100644
index 0000000..dfe9d6f
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/EditTextRule.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2010 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.ide.common.layout;
+
+import static com.android.ide.eclipse.adt.internal.editors.layout.descriptors.LayoutDescriptors.REQUEST_FOCUS;
+
+import com.android.ide.common.api.IMenuCallback;
+import com.android.ide.common.api.INode;
+import com.android.ide.common.api.INodeHandler;
+import com.android.ide.common.api.IViewRule;
+import com.android.ide.common.api.InsertType;
+import com.android.ide.common.api.MenuAction;
+
+import java.util.List;
+
+/**
+ * An {@link IViewRule} for android.widget.EditText.
+ */
+public class EditTextRule extends BaseViewRule {
+
+ @Override
+ public void onCreate(INode node, INode parent, InsertType insertType) {
+ super.onCreate(node, parent, insertType);
+
+ if (parent != null) {
+ INode focus = findFocus(findRoot(parent));
+ if (focus == null) {
+ // Add <requestFocus>
+ node.appendChild(REQUEST_FOCUS);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Adds a "Request Focus" menu item.
+ */
+ @Override
+ public List<MenuAction> getContextMenu(final INode selectedNode) {
+ final boolean hasFocus = hasFocus(selectedNode);
+ final String label = hasFocus ? "Clear Focus" : "Request Focus";
+
+ IMenuCallback onChange = new IMenuCallback() {
+ public void action(MenuAction menuAction, String valueId, Boolean newValue) {
+ selectedNode.editXml(label, new INodeHandler() {
+ public void handle(INode node) {
+ INode focus = findFocus(findRoot(node));
+ if (focus != null && focus.getParent() != null) {
+ focus.getParent().removeChild(focus);
+ }
+ if (!hasFocus) {
+ node.appendChild(REQUEST_FOCUS);
+ }
+ }
+ });
+ }
+ };
+
+ return concatenate(super.getContextMenu(selectedNode),
+ new MenuAction.Action("_setfocus", label, null, onChange)); //$NON-NLS-1$
+ }
+
+ /** Returns true if the given node currently has focus */
+ private static boolean hasFocus(INode node) {
+ INode focus = findFocus(node);
+ if (focus != null) {
+ return focus.getParent() == node;
+ }
+
+ return false;
+ }
+
+ /** Returns the root/top level node in the view hierarchy that contains the given node */
+ private static INode findRoot(INode node) {
+ // First find the parent
+ INode root = node;
+ while (root != null) {
+ INode parent = root.getParent();
+ if (parent == null) {
+ break;
+ } else {
+ root = parent;
+ }
+ }
+
+ return root;
+ }
+
+ /** Finds the focus node (not the node containing focus, but the actual request focus node
+ * under a given node */
+ private static INode findFocus(INode node) {
+ if (node.getFqcn().equals(REQUEST_FOCUS)) {
+ return node;
+ }
+
+ for (INode child : node.getChildren()) {
+ INode focus = findFocus(child);
+ if (focus != null) {
+ return focus;
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/LayoutConstants.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/LayoutConstants.java
index f88e7ab..bb04498 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/LayoutConstants.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/LayoutConstants.java
@@ -29,10 +29,10 @@ import com.android.sdklib.SdkConstants;
* </ul>
*/
public class LayoutConstants {
- /** The element name in a <code>&lt;view class="..."&gt;</code> element. */
+ /** The element name in a {@code <view class="...">} element. */
public static final String VIEW = "view"; //$NON-NLS-1$
- /** The attribute name in a <code>&lt;view class="..."&gt;</code> element. */
+ /** The attribute name in a {@code <view class="...">} element. */
public static final String ATTR_CLASS = "class"; //$NON-NLS-1$
public static final String ATTR_ON_CLICK = "onClick"; //$NON-NLS-1$
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/descriptors/DescriptorsUtils.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/descriptors/DescriptorsUtils.java
index 0384ad5..c7bc5a1 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/descriptors/DescriptorsUtils.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/descriptors/DescriptorsUtils.java
@@ -32,6 +32,7 @@ import static com.android.ide.common.layout.LayoutConstants.NEW_ID_PREFIX;
import static com.android.ide.common.layout.LayoutConstants.RELATIVE_LAYOUT;
import static com.android.ide.common.layout.LayoutConstants.VALUE_FILL_PARENT;
import static com.android.ide.common.layout.LayoutConstants.VALUE_WRAP_CONTENT;
+import static com.android.ide.eclipse.adt.internal.editors.layout.descriptors.LayoutDescriptors.REQUEST_FOCUS;
import com.android.ide.common.api.IAttributeInfo.Format;
import com.android.ide.common.resources.platform.AttributeInfo;
@@ -699,6 +700,12 @@ public final class DescriptorsUtils {
// if this ui_node is a layout and we're adding it to a document, use match_parent for
// both W/H. Otherwise default to wrap_layout.
ElementDescriptor descriptor = node.getDescriptor();
+
+ if (descriptor.getXmlLocalName().equals(REQUEST_FOCUS)) {
+ // Don't add ids etc to <requestFocus>
+ return;
+ }
+
boolean fill = descriptor.hasChildren() &&
node.getUiParent() instanceof UiDocumentNode;
node.setAttributeValue(
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors/LayoutDescriptors.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors/LayoutDescriptors.java
index b61c069..4613492 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors/LayoutDescriptors.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors/LayoutDescriptors.java
@@ -42,20 +42,27 @@ import java.util.Map.Entry;
public final class LayoutDescriptors implements IDescriptorProvider {
/**
- * The XML name of the special &lt;include&gt; layout tag.
+ * The XML name of the special {@code <include>} layout tag.
* A synthetic element with that name is created as part of the view descriptors list
* returned by {@link #getViewDescriptors()}.
*/
public static final String VIEW_INCLUDE = "include"; //$NON-NLS-1$
/**
- * The XML name of the special &lt;merge&gt; layout tag.
+ * The XML name of the special {@code <merge>} layout tag.
* A synthetic element with that name is created as part of the view descriptors list
* returned by {@link #getViewDescriptors()}.
*/
public static final String VIEW_MERGE = "merge"; //$NON-NLS-1$
/**
+ * The XML name of the special {@code <requestFocus>} layout tag.
+ * A synthetic element with that name is created as part of the view descriptors list
+ * returned by {@link #getViewDescriptors()}.
+ */
+ public static final String REQUEST_FOCUS = "requestFocus";//$NON-NLS-1$
+
+ /**
* The attribute name of the include tag's url naming the resource to be inserted
* <p>
* <b>NOTE</b>: The layout attribute is NOT in the Android namespace!
@@ -174,6 +181,10 @@ public final class LayoutDescriptors implements IDescriptorProvider {
fixSuperClasses(infoDescMap);
+ ViewElementDescriptor requestFocus = createRequestFocus();
+ newViews.add(requestFocus);
+ newDescriptors.add(requestFocus);
+
// The <merge> tag can only be a root tag, so it is added at the end.
// It gets everything else as children but it is not made a child itself.
ViewElementDescriptor mergeTag = createMerge(newLayouts);
@@ -342,7 +353,7 @@ public final class LayoutDescriptors implements IDescriptorProvider {
}
/**
- * Creates and return a new <merge> descriptor.
+ * Creates and return a new {@code <merge>} descriptor.
* @param knownLayouts A list of all known layout view descriptors, used to find the
* FrameLayout descriptor and extract its layout attributes.
*/
@@ -368,6 +379,27 @@ public final class LayoutDescriptors implements IDescriptorProvider {
}
/**
+ * Creates and return a new {@code <requestFocus>} descriptor.
+ * @param knownLayouts A list of all known layout view descriptors, used to find the
+ * FrameLayout descriptor and extract its layout attributes.
+ */
+ private ViewElementDescriptor createRequestFocus() {
+ String xml_name = REQUEST_FOCUS;
+
+ // Create the include descriptor
+ return new ViewElementDescriptor(
+ xml_name, // xml_name
+ xml_name, // ui_name
+ xml_name, // "class name"; the GLE only treats this as an element tag
+ "Requests focus for the parent element or one of its descendants", // tooltip
+ null, // sdk_url
+ null, // attributes
+ null, // layout attributes
+ null, // children
+ false /* mandatory */);
+ }
+
+ /**
* Finds the descriptor and retrieves all its layout attributes.
*/
private AttributeDescriptor[] findViewLayoutAttributes(
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/PaletteControl.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/PaletteControl.java
index f7f23da..2227531 100755
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/PaletteControl.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/PaletteControl.java
@@ -1125,9 +1125,11 @@ public class PaletteControl extends Composite {
final static int TOGGLE_ALPHABETICAL = 2;
final static int TOGGLE_AUTO_CLOSE = 3;
final static int REFRESH = 4;
+ final static int RESET = 5;
ToggleViewOptionAction(String title, int action, boolean checked) {
- super(title, action == REFRESH ? IAction.AS_PUSH_BUTTON : IAction.AS_CHECK_BOX);
+ super(title, (action == REFRESH || action == RESET) ? IAction.AS_PUSH_BUTTON
+ : IAction.AS_CHECK_BOX);
mAction = action;
if (checked) {
setChecked(checked);
@@ -1153,6 +1155,13 @@ public class PaletteControl extends Composite {
mPreviewIconFactory.refresh();
refreshPalette();
break;
+ case RESET:
+ mAlphabetical = false;
+ mCategories = true;
+ mAutoClose = true;
+ mPaletteMode = PaletteMode.SMALL_PREVIEW;
+ refreshPalette();
+ break;
}
savePaletteMode();
}
@@ -1197,6 +1206,11 @@ public class PaletteControl extends Composite {
manager.add(new ToggleViewOptionAction("Auto Close Previous",
ToggleViewOptionAction.TOGGLE_AUTO_CLOSE,
mAutoClose));
+ manager.add(new Separator());
+ manager.add(new ToggleViewOptionAction("Reset",
+ ToggleViewOptionAction.RESET,
+ false));
+
Menu menu = manager.createContextMenu(PaletteControl.this);
menu.setLocation(x, y);
menu.setVisible(true);
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/extra-view-metadata.xml b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/extra-view-metadata.xml
index 0870f69..442b76c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/extra-view-metadata.xml
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/extra-view-metadata.xml
@@ -298,6 +298,9 @@
<category
name="Advanced">
<view
+ class="requestFocus"
+ render="skip" />
+ <view
class="android.view.View"
render="skip" />
<view
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/AndroidLaunchController.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/AndroidLaunchController.java
index 930e8de..4db603e 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/AndroidLaunchController.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/AndroidLaunchController.java
@@ -44,9 +44,8 @@ import com.android.prefs.AndroidLocation.AndroidLocationException;
import com.android.sdklib.AndroidVersion;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.NullSdkLog;
-import com.android.sdklib.SdkConstants;
+import com.android.sdklib.internal.avd.AvdInfo;
import com.android.sdklib.internal.avd.AvdManager;
-import com.android.sdklib.internal.avd.AvdManager.AvdInfo;
import com.android.sdklib.xml.ManifestData;
import org.eclipse.core.resources.IFile;
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/DeviceChooserDialog.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/DeviceChooserDialog.java
index a9c8af8..b0dfea3 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/DeviceChooserDialog.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/DeviceChooserDialog.java
@@ -29,7 +29,7 @@ import com.android.ide.eclipse.adt.internal.sdk.Sdk;
import com.android.ide.eclipse.ddms.DdmsPlugin;
import com.android.sdklib.AndroidVersion;
import com.android.sdklib.IAndroidTarget;
-import com.android.sdklib.internal.avd.AvdManager.AvdInfo;
+import com.android.sdklib.internal.avd.AvdInfo;
import com.android.sdkuilib.internal.widgets.AvdSelector;
import com.android.sdkuilib.internal.widgets.AvdSelector.DisplayMode;
import com.android.sdkuilib.internal.widgets.AvdSelector.IAvdFilter;
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/EmulatorConfigTab.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/EmulatorConfigTab.java
index 3705cc2..1fc72fb 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/EmulatorConfigTab.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/EmulatorConfigTab.java
@@ -26,8 +26,8 @@ import com.android.ide.eclipse.adt.internal.sdk.Sdk;
import com.android.prefs.AndroidLocation.AndroidLocationException;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.NullSdkLog;
+import com.android.sdklib.internal.avd.AvdInfo;
import com.android.sdklib.internal.avd.AvdManager;
-import com.android.sdklib.internal.avd.AvdManager.AvdInfo;
import com.android.sdkuilib.internal.widgets.AvdSelector;
import com.android.sdkuilib.internal.widgets.AvdSelector.DisplayMode;
diff --git a/eclipse/scripts/create_ddms_symlinks.sh b/eclipse/scripts/create_ddms_symlinks.sh
index 8791316..48f5c51 100755
--- a/eclipse/scripts/create_ddms_symlinks.sh
+++ b/eclipse/scripts/create_ddms_symlinks.sh
@@ -63,11 +63,12 @@ for i in prebuilt/common/jfreechart/*.jar; do
cpfile $DEST $i
done
-LIBS="ddmlib ddmuilib"
+COPY_LIBS="ddmlib ddmuilib"
+ALL_LIBS="$COPY_LIBS swtmenubar"
echo "make java libs ..."
-make -j3 showcommands $LIBS || die "DDMS: Fail to build one of $LIBS."
+make -j3 showcommands $ALL_LIBS || die "DDMS: Fail to build one of $ALL_LIBS."
-for LIB in $LIBS; do
+for LIB in $COPY_LIBS; do
cpfile $DEST out/host/$PLATFORM/framework/$LIB.jar
done
diff --git a/eclipse/scripts/create_hierarchyviewer_symlinks.sh b/eclipse/scripts/create_hierarchyviewer_symlinks.sh
index e0439ef..47dbe7f 100755
--- a/eclipse/scripts/create_hierarchyviewer_symlinks.sh
+++ b/eclipse/scripts/create_hierarchyviewer_symlinks.sh
@@ -60,10 +60,11 @@ DEST=$BASE/libs
mkdir -p $DEST
-LIBS="hierarchyviewerlib "
+COPY_LIBS="hierarchyviewerlib"
+ALL_LIBS="$COPY_LIBS swtmenubar"
echo "make java libs ..."
-make -j3 showcommands $LIBS || die "Hierarchy Viewer: Fail to build one of $LIBS."
+make -j3 showcommands $ALL_LIBS || die "Hierarchy Viewer: Fail to build one of $ALL_LIBS."
-for LIB in $LIBS; do
+for LIB in $COPY_LIBS; do
cpfile $DEST out/host/$PLATFORM/framework/$LIB.jar
done
diff --git a/hierarchyviewer2/app/.classpath b/hierarchyviewer2/app/.classpath
index d75889a..c5a657c 100644
--- a/hierarchyviewer2/app/.classpath
+++ b/hierarchyviewer2/app/.classpath
@@ -7,5 +7,6 @@
<classpathentry combineaccessrules="false" kind="src" path="/ddmlib"/>
<classpathentry combineaccessrules="false" kind="src" path="/ddmuilib"/>
<classpathentry combineaccessrules="false" kind="src" path="/SdkLib"/>
+ <classpathentry kind="var" path="ANDROID_OUT_FRAMEWORK/swtmenubar.jar" sourcepath="/ANDROID_SRC/sdk/swtmenubar/src"/>
<classpathentry kind="output" path="bin"/>
</classpath>
diff --git a/hierarchyviewer2/app/Android.mk b/hierarchyviewer2/app/Android.mk
index d940403..0e00273 100644
--- a/hierarchyviewer2/app/Android.mk
+++ b/hierarchyviewer2/app/Android.mk
@@ -27,7 +27,8 @@ LOCAL_JAVA_LIBRARIES := \
swt \
org.eclipse.jface_3.4.2.M20090107-0800 \
org.eclipse.core.commands_3.4.0.I20080509-2000 \
- sdklib
+ sdklib \
+ swtmenubar
LOCAL_MODULE := hierarchyviewer2
diff --git a/hierarchyviewer2/app/README b/hierarchyviewer2/app/README
new file mode 100755
index 0000000..c00ef99
--- /dev/null
+++ b/hierarchyviewer2/app/README
@@ -0,0 +1,69 @@
+Using the Eclipse project HierarchyViewer
+-----------------------------------------
+
+HierarchyViewer requires some external libraries to compile.
+If you build HierarchyViewer using the makefile, you have nothing
+to configure. However if you want to develop on HierarchyViewer
+using Eclipse, you need to perform the following configuration.
+
+
+-------
+1- Projects required in Eclipse
+-------
+
+To run HierarchyViewer from Eclipse, you need to import the following 5 projects:
+
+ - sdk/hierarchyviewer2/app
+ - sdk/hierarchyviewer2/libs/hierarchyviewerlib/
+ - sdk/ddms/libs/ddmlib
+ - sdk/ddms/libs/ddmuilib
+ - sdk/sdkmanager/libs/sdklib
+
+
+-------
+2- HierarchyViewer requires some SWT JARs to compile.
+-------
+
+SWT is available in the tree under prebuild/<platform>/swt
+
+Because the build path cannot contain relative path that are not inside
+the project directory, the .classpath file references a user library
+called ANDROID_SWT.
+
+In order to compile the project:
+- Open Preferences > Java > Build Path > User Libraries
+
+- Create a new user library named ANDROID_SWT
+- Add the following 4 JAR files:
+
+ - prebuilt/<platform>/swt/swt.jar
+ - prebuilt/common/eclipse/org.eclipse.core.commands_3.*.jar
+ - prebuilt/common/eclipse/org.eclipse.equinox.common_3.*.jar
+ - prebuilt/common/eclipse/org.eclipse.jface_3.*.jar
+
+
+-------
+3- HierarchyViewer also requires the compiled SwtMenuBar library.
+-------
+
+Build the swtmenubar library:
+$ cd $TOP (top of Android tree)
+$ . build/envsetup.sh && lunch sdk-eng
+$ sdk/eclipse/scripts/create_sdkman_symlinks.sh
+
+Define a classpath variable in Eclipse:
+- Open Preferences > Java > Build Path > Classpath Variables
+- Create a new classpath variable named ANDROID_OUT_FRAMEWORK
+- Set its folder value to <Android tree>/out/host/<platform>/framework
+- Create a new classpath variable named ANDROID_SRC
+- Set its folder value to <Android tree>
+
+You might need to clean the ddms project (Project > Clean...) after
+you add the new classpath variable, otherwise previous errors might not
+go away automatically.
+
+The ANDROID_SRC part should be optional. It allows you to have access to
+the SwtMenuBar generic parts from the Java editor.
+
+--
+EOF
diff --git a/hierarchyviewer2/app/src/com/android/hierarchyviewer/AboutDialog.java b/hierarchyviewer2/app/src/com/android/hierarchyviewer/AboutDialog.java
index 3f973e7..150c70a 100644
--- a/hierarchyviewer2/app/src/com/android/hierarchyviewer/AboutDialog.java
+++ b/hierarchyviewer2/app/src/com/android/hierarchyviewer/AboutDialog.java
@@ -41,8 +41,8 @@ public class AboutDialog extends Dialog {
public AboutDialog(Shell shell) {
super(shell);
ImageLoader imageLoader = ImageLoader.getLoader(HierarchyViewerDirector.class);
- mSmallImage = imageLoader.loadImage("load-view-hierarchy.png", Display.getDefault()); //$NON-NLS-1$
- mAboutImage = imageLoader.loadImage("about.jpg", Display.getDefault()); //$NON-NLS-1$
+ mSmallImage = imageLoader.loadImage("sdk-hierarchyviewer-16.png", Display.getDefault()); //$NON-NLS-1$
+ mAboutImage = imageLoader.loadImage("sdk-hierarchyviewer-128.png", Display.getDefault()); //$NON-NLS-1$
}
@Override
diff --git a/hierarchyviewer2/app/src/com/android/hierarchyviewer/HierarchyViewerApplication.java b/hierarchyviewer2/app/src/com/android/hierarchyviewer/HierarchyViewerApplication.java
index 3a0a0e9..54a5fd6 100644
--- a/hierarchyviewer2/app/src/com/android/hierarchyviewer/HierarchyViewerApplication.java
+++ b/hierarchyviewer2/app/src/com/android/hierarchyviewer/HierarchyViewerApplication.java
@@ -53,11 +53,15 @@ import com.android.hierarchyviewerlib.ui.PropertyViewer;
import com.android.hierarchyviewerlib.ui.TreeView;
import com.android.hierarchyviewerlib.ui.TreeViewControls;
import com.android.hierarchyviewerlib.ui.TreeViewOverview;
+import com.android.menubar.IMenuBarEnhancer;
+import com.android.menubar.MenuBarEnhancer;
+import com.android.menubar.IMenuBarEnhancer.MenuBarMode;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.window.ApplicationWindow;
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.SelectionEvent;
@@ -81,6 +85,7 @@ import org.eclipse.swt.widgets.Shell;
public class HierarchyViewerApplication extends ApplicationWindow {
+ private static final String APP_NAME = "Hierarchy Viewer";
private static final int INITIAL_WIDTH = 1024;
private static final int INITIAL_HEIGHT = 768;
@@ -148,7 +153,7 @@ public class HierarchyViewerApplication extends ApplicationWindow {
@Override
protected void configureShell(Shell shell) {
super.configureShell(shell);
- shell.setText("Hierarchy Viewer");
+ shell.setText(APP_NAME);
ImageLoader imageLoader = ImageLoader.getLoader(HierarchyViewerDirector.class);
Image image = imageLoader.loadImage("sdk-hierarchyviewer-128.png", Display.getDefault()); //$NON-NLS-1$
shell.setImage(image);
@@ -162,7 +167,14 @@ public class HierarchyViewerApplication extends ApplicationWindow {
public void run() {
setBlockOnOpen(true);
- open();
+ try {
+ open();
+ } catch (SWTException e) {
+ // Ignore "widget disposed" errors after we closed.
+ if (!getShell().isDisposed()) {
+ throw e;
+ }
+ }
TreeViewModel.getModel().removeTreeChangeListener(mTreeChangeListener);
PixelPerfectModel.getModel().removeImageChangeListener(mImageChangeListener);
@@ -581,12 +593,16 @@ public class HierarchyViewerApplication extends ApplicationWindow {
MenuManager mm = getMenuBarManager();
mm.removeAll();
- String os = System.getProperty("os.name"); //$NON-NLS-1$
- if (os.startsWith("Mac OS") == false) { //$NON-NLS-1$
- MenuManager file = new MenuManager("&File");
+ MenuManager file = new MenuManager("&File");
+ IMenuBarEnhancer enhancer = MenuBarEnhancer.setupMenuManager(
+ APP_NAME,
+ getShell().getDisplay(),
+ file,
+ AboutAction.getAction(getShell()),
+ null /*preferencesAction*/,
+ QuitAction.getAction());
+ if (enhancer.getMenuBarMode() == MenuBarMode.GENERIC) {
mm.add(file);
-
- file.add(QuitAction.getAction());
}
MenuManager device = new MenuManager("&Devices");
@@ -596,11 +612,6 @@ public class HierarchyViewerApplication extends ApplicationWindow {
device.add(LoadViewHierarchyAction.getAction());
device.add(InspectScreenshotAction.getAction());
- MenuManager help = new MenuManager("&Help");
- mm.add(help);
-
- help.add(AboutAction.getAction(getShell()));
-
mm.updateAll(true);
mDeviceViewButton.setSelection(true);
@@ -626,12 +637,16 @@ public class HierarchyViewerApplication extends ApplicationWindow {
MenuManager mm = getMenuBarManager();
mm.removeAll();
- String os = System.getProperty("os.name"); //$NON-NLS-1$
- if (os.startsWith("Mac OS") == false) { //$NON-NLS-1$
- MenuManager file = new MenuManager("&File");
+ MenuManager file = new MenuManager("&File");
+ IMenuBarEnhancer enhancer = MenuBarEnhancer.setupMenuManager(
+ APP_NAME,
+ getShell().getDisplay(),
+ file,
+ AboutAction.getAction(getShell()),
+ null /*preferencesAction*/,
+ QuitAction.getAction());
+ if (enhancer.getMenuBarMode() == MenuBarMode.GENERIC) {
mm.add(file);
-
- file.add(QuitAction.getAction());
}
MenuManager treeViewMenu = new MenuManager("&Tree View");
@@ -646,11 +661,6 @@ public class HierarchyViewerApplication extends ApplicationWindow {
treeViewMenu.add(InvalidateAction.getAction());
treeViewMenu.add(RequestLayoutAction.getAction());
- MenuManager help = new MenuManager("&Help");
- mm.add(help);
-
- help.add(AboutAction.getAction(getShell()));
-
mm.updateAll(true);
mDeviceViewButton.setSelection(false);
@@ -676,12 +686,16 @@ public class HierarchyViewerApplication extends ApplicationWindow {
MenuManager mm = getMenuBarManager();
mm.removeAll();
- String os = System.getProperty("os.name"); //$NON-NLS-1$
- if (os.startsWith("Mac OS") == false) { //$NON-NLS-1$
- MenuManager file = new MenuManager("&File");
+ MenuManager file = new MenuManager("&File");
+ IMenuBarEnhancer enhancer = MenuBarEnhancer.setupMenuManager(
+ APP_NAME,
+ getShell().getDisplay(),
+ file,
+ AboutAction.getAction(getShell()),
+ null /*preferencesAction*/,
+ QuitAction.getAction());
+ if (enhancer.getMenuBarMode() == MenuBarMode.GENERIC) {
mm.add(file);
-
- file.add(QuitAction.getAction());
}
MenuManager pixelPerfect = new MenuManager("&Pixel Perfect");
@@ -695,11 +709,6 @@ public class HierarchyViewerApplication extends ApplicationWindow {
mm.add(pixelPerfect);
- MenuManager help = new MenuManager("&Help");
- mm.add(help);
-
- help.add(AboutAction.getAction(getShell()));
-
mm.updateAll(true);
mDeviceViewButton.setSelection(false);
diff --git a/hierarchyviewer2/app/src/com/android/hierarchyviewer/actions/AboutAction.java b/hierarchyviewer2/app/src/com/android/hierarchyviewer/actions/AboutAction.java
index 0c7c7b2..332b2dc 100644
--- a/hierarchyviewer2/app/src/com/android/hierarchyviewer/actions/AboutAction.java
+++ b/hierarchyviewer2/app/src/com/android/hierarchyviewer/actions/AboutAction.java
@@ -41,7 +41,7 @@ public class AboutAction extends Action implements ImageAction {
this.mShell = shell;
setAccelerator(SWT.MOD1 + 'A');
ImageLoader imageLoader = ImageLoader.getLoader(HierarchyViewerDirector.class);
- mImage = imageLoader.loadImage("about-small.jpg", Display.getDefault()); //$NON-NLS-1$
+ mImage = imageLoader.loadImage("sdk-hierarchyviewer-16.png", Display.getDefault()); //$NON-NLS-1$
setImageDescriptor(ImageDescriptor.createFromImage(mImage));
setToolTipText("Shows the about dialog");
}
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/Android.mk b/hierarchyviewer2/libs/hierarchyviewerlib/src/Android.mk
index ded20e1..3ca63dd 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/Android.mk
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/Android.mk
@@ -16,7 +16,7 @@ LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-subdir-java-files)
-LOCAL_JAVA_RESOURCE_DIRS := resources
+LOCAL_JAVA_RESOURCE_DIRS := ../src
LOCAL_JAR_MANIFEST := ../manifest.txt
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/auto-refresh.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/auto-refresh.png
index 240862f..240862f 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/auto-refresh.png
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/auto-refresh.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/capture-psd.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/capture-psd.png
index 0f25426..0f25426 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/capture-psd.png
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/capture-psd.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/device-view-selected.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/device-view-selected.png
index fd107ed..fd107ed 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/device-view-selected.png
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/device-view-selected.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/device-view.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/device-view.png
index 9a7eed4..9a7eed4 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/device-view.png
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/device-view.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/display.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/display.png
index a9de0ec..a9de0ec 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/display.png
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/display.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/filtered.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/filtered.png
index 4fcab3f..4fcab3f 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/filtered.png
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/filtered.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/green.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/green.png
index 800000d..800000d 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/green.png
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/green.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/inspect-screenshot.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/inspect-screenshot.png
index 6e51701..6e51701 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/inspect-screenshot.png
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/inspect-screenshot.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/invalidate.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/invalidate.png
index ee75f69..ee75f69 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/invalidate.png
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/invalidate.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/load-all-views.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/load-all-views.png
index 3329ec9..3329ec9 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/load-all-views.png
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/load-all-views.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/load-overlay.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/load-overlay.png
index 4817252..4817252 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/load-overlay.png
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/load-overlay.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/load-view-hierarchy.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/load-view-hierarchy.png
index 8f01dda..8f01dda 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/load-view-hierarchy.png
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/load-view-hierarchy.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/not-selected.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/not-selected.png
index db6f13b..db6f13b 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/not-selected.png
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/not-selected.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/on-black.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/on-black.png
index cd88803..cd88803 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/on-black.png
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/on-black.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/on-white.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/on-white.png
index 5f05662..5f05662 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/on-white.png
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/on-white.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/pixel-perfect-view-selected.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/pixel-perfect-view-selected.png
index 1e44000..1e44000 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/pixel-perfect-view-selected.png
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/pixel-perfect-view-selected.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/pixel-perfect-view.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/pixel-perfect-view.png
index ec51cec..ec51cec 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/pixel-perfect-view.png
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/pixel-perfect-view.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/red.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/red.png
index a2ab855..a2ab855 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/red.png
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/red.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/refresh-windows.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/refresh-windows.png
index 8fddcae..8fddcae 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/refresh-windows.png
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/refresh-windows.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/request-layout.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/request-layout.png
index 92a78c8..92a78c8 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/request-layout.png
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/request-layout.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/save.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/save.png
index 2c0bab1..2c0bab1 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/save.png
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/save.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/sdk-hierarchyviewer-128.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/sdk-hierarchyviewer-128.png
index 4535f22..4535f22 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/sdk-hierarchyviewer-128.png
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/sdk-hierarchyviewer-128.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/images/sdk-hierarchyviewer-16.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/sdk-hierarchyviewer-16.png
new file mode 100755
index 0000000..8c3c23d
--- /dev/null
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/sdk-hierarchyviewer-16.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/selected-filtered-small.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/selected-filtered-small.png
index 9ef6b34..9ef6b34 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/selected-filtered-small.png
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/selected-filtered-small.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/selected-filtered.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/selected-filtered.png
index 1f59685..1f59685 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/selected-filtered.png
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/selected-filtered.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/selected-small.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/selected-small.png
index 538e385..538e385 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/selected-small.png
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/selected-small.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/selected.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/selected.png
index 5cd5c3f..5cd5c3f 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/selected.png
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/selected.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/show-extras.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/show-extras.png
index ba9c305..ba9c305 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/show-extras.png
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/show-extras.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/show-overlay.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/show-overlay.png
index e39e90a..e39e90a 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/show-overlay.png
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/show-overlay.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/tree-view-selected.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/tree-view-selected.png
index 175ad1f..175ad1f 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/tree-view-selected.png
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/tree-view-selected.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/tree-view.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/tree-view.png
index 23aa424..23aa424 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/tree-view.png
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/tree-view.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/yellow.png b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/yellow.png
index e9b5781..e9b5781 100644
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/yellow.png
+++ b/hierarchyviewer2/libs/hierarchyviewerlib/src/images/yellow.png
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/about-small.jpg b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/about-small.jpg
deleted file mode 100644
index 6fe9291..0000000
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/about-small.jpg
+++ /dev/null
Binary files differ
diff --git a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/about.jpg b/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/about.jpg
deleted file mode 100644
index 8e10514..0000000
--- a/hierarchyviewer2/libs/hierarchyviewerlib/src/resources/images/about.jpg
+++ /dev/null
Binary files differ
diff --git a/sdkmanager/app/etc/android b/sdkmanager/app/etc/android
index 2e17009..57ce733 100755
--- a/sdkmanager/app/etc/android
+++ b/sdkmanager/app/etc/android
@@ -105,9 +105,5 @@ if [ ! -d "$swtpath" ]; then
exit 1
fi
-if [ -z "$1" ]; then
- echo "Starting Android SDK and AVD Manager"
-fi
-
# need to use "java.ext.dirs" because "-jar" causes classpath to be ignored
exec "$java_cmd" -Xmx256M $os_opts $java_debug -Dcom.android.sdkmanager.toolsdir="$progdir" -classpath "$jarpath:$swtpath/swt.jar" com.android.sdkmanager.Main "$@"
diff --git a/sdkmanager/app/etc/android.bat b/sdkmanager/app/etc/android.bat
index daa6b8a..d4b5939 100755
--- a/sdkmanager/app/etc/android.bat
+++ b/sdkmanager/app/etc/android.bat
@@ -45,7 +45,7 @@ for /f %%a in ('%java_exe% -jar lib\archquery.jar') do set swt_path=lib\%%a
if "%1 %2"=="update sdk" goto StartUi
if not "%1"=="" goto EndTempCopy
:StartUi
- echo [INFO] Starting Android SDK and AVD Manager
+ rem Starting Android SDK and AVD Manager UI
rem We're now going to create a temp dir to hold all the Jar files needed
rem to run the android tool, copy them in the temp dir and finally execute
diff --git a/sdkmanager/app/src/com/android/sdkmanager/Main.java b/sdkmanager/app/src/com/android/sdkmanager/Main.java
index 3936286..5ac5f4c 100644
--- a/sdkmanager/app/src/com/android/sdkmanager/Main.java
+++ b/sdkmanager/app/src/com/android/sdkmanager/Main.java
@@ -26,9 +26,9 @@ import com.android.sdklib.ISdkLog;
import com.android.sdklib.SdkConstants;
import com.android.sdklib.SdkManager;
import com.android.sdklib.IAndroidTarget.IOptionalLibrary;
+import com.android.sdklib.internal.avd.AvdInfo;
import com.android.sdklib.internal.avd.AvdManager;
import com.android.sdklib.internal.avd.HardwareProperties;
-import com.android.sdklib.internal.avd.AvdManager.AvdInfo;
import com.android.sdklib.internal.avd.HardwareProperties.HardwareProperty;
import com.android.sdklib.internal.project.ProjectCreator;
import com.android.sdklib.internal.project.ProjectProperties;
@@ -306,10 +306,6 @@ public class Main {
*/
private void showMainWindow(boolean autoUpdate) {
try {
- // display a message talking about the command line version
- System.out.printf("No command line parameters provided, launching UI.\n" +
- "See 'android --help' for operations from the command line.\n");
-
MessageBoxLog errorLogger = new MessageBoxLog(
"SDK Manager",
Display.getCurrent(),
@@ -784,6 +780,18 @@ public class Main {
* Displays the list of available Targets (Platforms and Add-ons)
*/
private void displayTargetList() {
+
+ // Compact output, suitable for scripts.
+ if (mSdkCommandLine != null && mSdkCommandLine.getFlagCompact()) {
+ char eol = mSdkCommandLine.getFlagEolNull() ? '\0' : '\n';
+
+ for (IAndroidTarget target : mSdkManager.getTargets()) {
+ mSdkLog.printf("%1$s%2$c", target.hashString(), eol);
+ }
+
+ return;
+ }
+
mSdkLog.printf("Available Android targets:\n");
int index = 1;
@@ -862,16 +870,30 @@ public class Main {
* @param avdManager
*/
public void displayAvdList(AvdManager avdManager) {
- mSdkLog.printf("Available Android Virtual Devices:\n");
AvdInfo[] avds = avdManager.getValidAvds();
+
+ // Compact output, suitable for scripts.
+ if (mSdkCommandLine != null && mSdkCommandLine.getFlagCompact()) {
+ char eol = mSdkCommandLine.getFlagEolNull() ? '\0' : '\n';
+
+ for (int index = 0 ; index < avds.length ; index++) {
+ AvdInfo info = avds[index];
+ mSdkLog.printf("%1$s%2$c", info.getName(), eol);
+ }
+
+ return;
+ }
+
+ mSdkLog.printf("Available Android Virtual Devices:\n");
+
for (int index = 0 ; index < avds.length ; index++) {
AvdInfo info = avds[index];
if (index > 0) {
mSdkLog.printf("---------\n");
}
mSdkLog.printf(" Name: %s\n", info.getName());
- mSdkLog.printf(" Path: %s\n", info.getPath());
+ mSdkLog.printf(" Path: %s\n", info.getDataFolderPath());
// get the target of the AVD
IAndroidTarget target = info.getTarget();
@@ -920,7 +942,8 @@ public class Main {
mSdkLog.printf("---------\n");
}
mSdkLog.printf(" Name: %s\n", info.getName() == null ? "--" : info.getName());
- mSdkLog.printf(" Path: %s\n", info.getPath() == null ? "--" : info.getPath());
+ mSdkLog.printf(" Path: %s\n",
+ info.getDataFolderPath() == null ? "--" : info.getDataFolderPath());
String error = info.getErrorMessage();
mSdkLog.printf(" Error: %s\n", error == null ? "Uknown error" : error);
@@ -987,7 +1010,7 @@ public class Main {
if (paramFolderPath != null) {
avdFolder = new File(paramFolderPath);
} else {
- avdFolder = AvdManager.AvdInfo.getAvdFolder(avdName);
+ avdFolder = AvdInfo.getDefaultAvdFolder(avdManager, avdName);
}
// Validate skin is either default (empty) or NNNxMMM or a valid skin name.
@@ -1113,7 +1136,7 @@ public class Main {
// check if paths are the same. Use File methods to account for OS idiosyncrasies.
try {
File f1 = new File(paramFolderPath).getCanonicalFile();
- File f2 = new File(info.getPath()).getCanonicalFile();
+ File f2 = new File(info.getDataFolderPath()).getCanonicalFile();
if (f1.equals(f2)) {
// same canonical path, so not actually a move
paramFolderPath = null;
@@ -1139,7 +1162,7 @@ public class Main {
File originalFolder = new File(
AndroidLocation.getFolder() + AndroidLocation.FOLDER_AVD,
info.getName() + AvdManager.AVD_FOLDER_EXTENSION);
- if (originalFolder.equals(info.getPath())) {
+ if (originalFolder.equals(info.getDataFolderPath())) {
try {
// The AVD is using the default data folder path based on the AVD name.
// That folder needs to be adjusted to use the new name.
@@ -1161,7 +1184,7 @@ public class Main {
}
File ini = info.getIniFile();
- if (ini.equals(AvdInfo.getIniFile(newName))) {
+ if (ini.equals(AvdInfo.getDefaultIniFile(avdManager, newName))) {
errorAndExit("The AVD file '%s' is in the way.", ini.getCanonicalPath());
return;
}
diff --git a/sdkmanager/app/src/com/android/sdkmanager/SdkCommandLine.java b/sdkmanager/app/src/com/android/sdkmanager/SdkCommandLine.java
index 157e896..fb15cb5 100644
--- a/sdkmanager/app/src/com/android/sdkmanager/SdkCommandLine.java
+++ b/sdkmanager/app/src/com/android/sdkmanager/SdkCommandLine.java
@@ -38,47 +38,49 @@ class SdkCommandLine extends CommandLineProcessor {
* or optional) for the given action.
*/
- public final static String VERB_LIST = "list";
- public final static String VERB_CREATE = "create";
- public final static String VERB_MOVE = "move";
- public final static String VERB_DELETE = "delete";
- public final static String VERB_UPDATE = "update";
-
- public static final String OBJECT_SDK = "sdk";
- public static final String OBJECT_AVD = "avd";
- public static final String OBJECT_AVDS = "avds";
- public static final String OBJECT_TARGET = "target";
- public static final String OBJECT_TARGETS = "targets";
- public static final String OBJECT_PROJECT = "project";
- public static final String OBJECT_TEST_PROJECT = "test-project";
- public static final String OBJECT_LIB_PROJECT = "lib-project";
- public static final String OBJECT_EXPORT_PROJECT = "export-project";
- public static final String OBJECT_ADB = "adb";
-
- public static final String ARG_ALIAS = "alias";
- public static final String ARG_ACTIVITY = "activity";
+ public final static String VERB_LIST = "list"; //$NON-NLS-1$
+ public final static String VERB_CREATE = "create"; //$NON-NLS-1$
+ public final static String VERB_MOVE = "move"; //$NON-NLS-1$
+ public final static String VERB_DELETE = "delete"; //$NON-NLS-1$
+ public final static String VERB_UPDATE = "update"; //$NON-NLS-1$
+
+ public static final String OBJECT_SDK = "sdk"; //$NON-NLS-1$
+ public static final String OBJECT_AVD = "avd"; //$NON-NLS-1$
+ public static final String OBJECT_AVDS = "avds"; //$NON-NLS-1$
+ public static final String OBJECT_TARGET = "target"; //$NON-NLS-1$
+ public static final String OBJECT_TARGETS = "targets"; //$NON-NLS-1$
+ public static final String OBJECT_PROJECT = "project"; //$NON-NLS-1$
+ public static final String OBJECT_TEST_PROJECT = "test-project"; //$NON-NLS-1$
+ public static final String OBJECT_LIB_PROJECT = "lib-project"; //$NON-NLS-1$
+ public static final String OBJECT_EXPORT_PROJECT = "export-project"; //$NON-NLS-1$
+ public static final String OBJECT_ADB = "adb"; //$NON-NLS-1$
+
+ public static final String ARG_ALIAS = "alias"; //$NON-NLS-1$
+ public static final String ARG_ACTIVITY = "activity"; //$NON-NLS-1$
public static final String KEY_ACTIVITY = ARG_ACTIVITY;
- public static final String KEY_PACKAGE = "package";
- public static final String KEY_MODE = "mode";
+ public static final String KEY_PACKAGE = "package"; //$NON-NLS-1$
+ public static final String KEY_MODE = "mode"; //$NON-NLS-1$
public static final String KEY_TARGET_ID = OBJECT_TARGET;
- public static final String KEY_NAME = "name";
- public static final String KEY_LIBRARY = "library";
- public static final String KEY_PATH = "path";
- public static final String KEY_FILTER = "filter";
- public static final String KEY_SKIN = "skin";
- public static final String KEY_SDCARD = "sdcard";
- public static final String KEY_FORCE = "force";
- public static final String KEY_RENAME = "rename";
- public static final String KEY_SUBPROJECTS = "subprojects";
- public static final String KEY_MAIN_PROJECT = "main";
- public static final String KEY_NO_UI = "no-ui";
- public static final String KEY_NO_HTTPS = "no-https";
- public static final String KEY_PROXY_PORT = "proxy-port";
- public static final String KEY_PROXY_HOST = "proxy-host";
- public static final String KEY_DRY_MODE = "dry-mode";
- public static final String KEY_OBSOLETE = "obsolete";
- public static final String KEY_SNAPSHOT = "snapshot";
+ public static final String KEY_NAME = "name"; //$NON-NLS-1$
+ public static final String KEY_LIBRARY = "library"; //$NON-NLS-1$
+ public static final String KEY_PATH = "path"; //$NON-NLS-1$
+ public static final String KEY_FILTER = "filter"; //$NON-NLS-1$
+ public static final String KEY_SKIN = "skin"; //$NON-NLS-1$
+ public static final String KEY_SDCARD = "sdcard"; //$NON-NLS-1$
+ public static final String KEY_FORCE = "force"; //$NON-NLS-1$
+ public static final String KEY_RENAME = "rename"; //$NON-NLS-1$
+ public static final String KEY_SUBPROJECTS = "subprojects"; //$NON-NLS-1$
+ public static final String KEY_MAIN_PROJECT = "main"; //$NON-NLS-1$
+ public static final String KEY_NO_UI = "no-ui"; //$NON-NLS-1$
+ public static final String KEY_NO_HTTPS = "no-https"; //$NON-NLS-1$
+ public static final String KEY_PROXY_PORT = "proxy-port"; //$NON-NLS-1$
+ public static final String KEY_PROXY_HOST = "proxy-host"; //$NON-NLS-1$
+ public static final String KEY_DRY_MODE = "dry-mode"; //$NON-NLS-1$
+ public static final String KEY_OBSOLETE = "obsolete"; //$NON-NLS-1$
+ public static final String KEY_SNAPSHOT = "snapshot"; //$NON-NLS-1$
+ public static final String KEY_COMPACT = "compact"; //$NON-NLS-1$
+ public static final String KEY_EOL_NULL = "null"; //$NON-NLS-1$
/**
* Action definitions for SdkManager command line.
@@ -149,117 +151,139 @@ class SdkCommandLine extends CommandLineProcessor {
// The following defines the parameters of the actions defined in mAction.
+ // --- list avds ---
+
+ define(Mode.BOOLEAN, false,
+ VERB_LIST, OBJECT_AVD, "c", KEY_COMPACT, //$NON-NLS-1$
+ "Compact output (suitable for scripts)", false);
+
+ define(Mode.BOOLEAN, false,
+ VERB_LIST, OBJECT_AVD, "0", KEY_EOL_NULL, //$NON-NLS-1$
+ "Terminates lines with \\0 instead of \\n (e.g. for xargs -0). Only used by --" + KEY_COMPACT + ".",
+ false);
+
+ // --- list targets ---
+
+ define(Mode.BOOLEAN, false,
+ VERB_LIST, OBJECT_TARGET, "c", KEY_COMPACT, //$NON-NLS-1$
+ "Compact output (suitable for scripts)", false);
+
+ define(Mode.BOOLEAN, false,
+ VERB_LIST, OBJECT_TARGET, "0", KEY_EOL_NULL, //$NON-NLS-1$
+ "Terminates lines with \\0 instead of \\n (e.g. for xargs -0) Only used by --" + KEY_COMPACT + ".",
+ false);
+
// --- create avd ---
define(Mode.STRING, false,
- VERB_CREATE, OBJECT_AVD, "p", KEY_PATH,
+ VERB_CREATE, OBJECT_AVD, "p", KEY_PATH, //$NON-NLS-1$
"Directory where the new AVD will be created", null);
define(Mode.STRING, true,
- VERB_CREATE, OBJECT_AVD, "n", KEY_NAME,
+ VERB_CREATE, OBJECT_AVD, "n", KEY_NAME, //$NON-NLS-1$
"Name of the new AVD", null);
define(Mode.STRING, true,
- VERB_CREATE, OBJECT_AVD, "t", KEY_TARGET_ID,
+ VERB_CREATE, OBJECT_AVD, "t", KEY_TARGET_ID, //$NON-NLS-1$
"Target ID of the new AVD", null);
define(Mode.STRING, false,
- VERB_CREATE, OBJECT_AVD, "s", KEY_SKIN,
+ VERB_CREATE, OBJECT_AVD, "s", KEY_SKIN, //$NON-NLS-1$
"Skin for the new AVD", null);
define(Mode.STRING, false,
- VERB_CREATE, OBJECT_AVD, "c", KEY_SDCARD,
+ VERB_CREATE, OBJECT_AVD, "c", KEY_SDCARD, //$NON-NLS-1$
"Path to a shared SD card image, or size of a new sdcard for the new AVD", null);
define(Mode.BOOLEAN, false,
- VERB_CREATE, OBJECT_AVD, "f", KEY_FORCE,
+ VERB_CREATE, OBJECT_AVD, "f", KEY_FORCE, //$NON-NLS-1$
"Forces creation (overwrites an existing AVD)", false);
define(Mode.BOOLEAN, false,
- VERB_CREATE, OBJECT_AVD, "a", KEY_SNAPSHOT,
+ VERB_CREATE, OBJECT_AVD, "a", KEY_SNAPSHOT, //$NON-NLS-1$
"Place a snapshots file in the AVD, to enable persistence.", false);
// --- delete avd ---
define(Mode.STRING, true,
- VERB_DELETE, OBJECT_AVD, "n", KEY_NAME,
+ VERB_DELETE, OBJECT_AVD, "n", KEY_NAME, //$NON-NLS-1$
"Name of the AVD to delete", null);
// --- move avd ---
define(Mode.STRING, true,
- VERB_MOVE, OBJECT_AVD, "n", KEY_NAME,
+ VERB_MOVE, OBJECT_AVD, "n", KEY_NAME, //$NON-NLS-1$
"Name of the AVD to move or rename", null);
define(Mode.STRING, false,
- VERB_MOVE, OBJECT_AVD, "r", KEY_RENAME,
+ VERB_MOVE, OBJECT_AVD, "r", KEY_RENAME, //$NON-NLS-1$
"New name of the AVD", null);
define(Mode.STRING, false,
- VERB_MOVE, OBJECT_AVD, "p", KEY_PATH,
+ VERB_MOVE, OBJECT_AVD, "p", KEY_PATH, //$NON-NLS-1$
"Path to the AVD's new directory", null);
// --- update avd ---
define(Mode.STRING, true,
- VERB_UPDATE, OBJECT_AVD, "n", KEY_NAME,
+ VERB_UPDATE, OBJECT_AVD, "n", KEY_NAME, //$NON-NLS-1$
"Name of the AVD to update", null);
// --- list sdk ---
define(Mode.BOOLEAN, false,
- VERB_LIST, OBJECT_SDK, "u", KEY_NO_UI,
+ VERB_LIST, OBJECT_SDK, "u", KEY_NO_UI, //$NON-NLS-1$
"Displays list result on console (no GUI)", true);
define(Mode.BOOLEAN, false,
- VERB_LIST, OBJECT_SDK, "s", KEY_NO_HTTPS,
+ VERB_LIST, OBJECT_SDK, "s", KEY_NO_HTTPS, //$NON-NLS-1$
"Uses HTTP instead of HTTPS (the default) for downloads", false);
define(Mode.STRING, false,
- VERB_LIST, OBJECT_SDK, "", KEY_PROXY_PORT,
+ VERB_LIST, OBJECT_SDK, "", KEY_PROXY_PORT, //$NON-NLS-1$
"HTTP/HTTPS proxy port (overrides settings if defined)",
null);
define(Mode.STRING, false,
- VERB_LIST, OBJECT_SDK, "", KEY_PROXY_HOST,
+ VERB_LIST, OBJECT_SDK, "", KEY_PROXY_HOST, //$NON-NLS-1$
"HTTP/HTTPS proxy host (overrides settings if defined)",
null);
define(Mode.BOOLEAN, false,
- VERB_LIST, OBJECT_SDK, "o", KEY_OBSOLETE,
+ VERB_LIST, OBJECT_SDK, "o", KEY_OBSOLETE, //$NON-NLS-1$
"Installs obsolete packages",
false);
// --- update sdk ---
define(Mode.BOOLEAN, false,
- VERB_UPDATE, OBJECT_SDK, "u", KEY_NO_UI,
+ VERB_UPDATE, OBJECT_SDK, "u", KEY_NO_UI, //$NON-NLS-1$
"Updates from command-line (does not display the GUI)", false);
define(Mode.BOOLEAN, false,
- VERB_UPDATE, OBJECT_SDK, "s", KEY_NO_HTTPS,
+ VERB_UPDATE, OBJECT_SDK, "s", KEY_NO_HTTPS, //$NON-NLS-1$
"Uses HTTP instead of HTTPS (the default) for downloads", false);
define(Mode.STRING, false,
- VERB_UPDATE, OBJECT_SDK, "", KEY_PROXY_PORT,
+ VERB_UPDATE, OBJECT_SDK, "", KEY_PROXY_PORT, //$NON-NLS-1$
"HTTP/HTTPS proxy port (overrides settings if defined)",
null);
define(Mode.STRING, false,
- VERB_UPDATE, OBJECT_SDK, "", KEY_PROXY_HOST,
+ VERB_UPDATE, OBJECT_SDK, "", KEY_PROXY_HOST, //$NON-NLS-1$
"HTTP/HTTPS proxy host (overrides settings if defined)",
null);
define(Mode.BOOLEAN, false,
- VERB_UPDATE, OBJECT_SDK, "f", KEY_FORCE,
+ VERB_UPDATE, OBJECT_SDK, "f", KEY_FORCE, //$NON-NLS-1$
"Forces replacement of a package or its parts, even if something has been modified",
false);
define(Mode.STRING, false,
- VERB_UPDATE, OBJECT_SDK, "t", KEY_FILTER,
+ VERB_UPDATE, OBJECT_SDK, "t", KEY_FILTER, //$NON-NLS-1$
"A filter that limits the update to the specified types of packages in the form of\n" +
"a comma-separated list of " + Arrays.toString(SdkRepoConstants.NODES),
null);
define(Mode.BOOLEAN, false,
- VERB_UPDATE, OBJECT_SDK, "o", KEY_OBSOLETE,
+ VERB_UPDATE, OBJECT_SDK, "o", KEY_OBSOLETE, //$NON-NLS-1$
"Installs obsolete packages",
false);
define(Mode.BOOLEAN, false,
- VERB_UPDATE, OBJECT_SDK, "n", KEY_DRY_MODE,
+ VERB_UPDATE, OBJECT_SDK, "n", KEY_DRY_MODE, //$NON-NLS-1$
"Simulates the update but does not download or install anything",
false);
@@ -269,7 +293,7 @@ class SdkCommandLine extends CommandLineProcessor {
This currently does not work, the alias build rules need to be fixed.
define(Mode.ENUM, true,
- VERB_CREATE, OBJECT_PROJECT, "m", KEY_MODE,
+ VERB_CREATE, OBJECT_PROJECT, "m", KEY_MODE, //$NON-NLS-1$
"Project mode", new String[] { ARG_ACTIVITY, ARG_ALIAS });
*/
define(Mode.STRING, true,
@@ -277,46 +301,44 @@ class SdkCommandLine extends CommandLineProcessor {
"p", KEY_PATH,
"The new project's directory", null);
define(Mode.STRING, true,
- VERB_CREATE, OBJECT_PROJECT, "t", KEY_TARGET_ID,
+ VERB_CREATE, OBJECT_PROJECT, "t", KEY_TARGET_ID, //$NON-NLS-1$
"Target ID of the new project", null);
define(Mode.STRING, true,
- VERB_CREATE, OBJECT_PROJECT, "k", KEY_PACKAGE,
+ VERB_CREATE, OBJECT_PROJECT, "k", KEY_PACKAGE, //$NON-NLS-1$
"Android package name for the application", null);
define(Mode.STRING, true,
- VERB_CREATE, OBJECT_PROJECT, "a", KEY_ACTIVITY,
+ VERB_CREATE, OBJECT_PROJECT, "a", KEY_ACTIVITY, //$NON-NLS-1$
"Name of the default Activity that is created", null);
define(Mode.STRING, false,
- VERB_CREATE, OBJECT_PROJECT, "n", KEY_NAME,
+ VERB_CREATE, OBJECT_PROJECT, "n", KEY_NAME, //$NON-NLS-1$
"Project name", null);
// --- create test-project ---
define(Mode.STRING, true,
- VERB_CREATE, OBJECT_TEST_PROJECT,
- "p", KEY_PATH,
+ VERB_CREATE, OBJECT_TEST_PROJECT, "p", KEY_PATH, //$NON-NLS-1$
"The new project's directory", null);
define(Mode.STRING, false,
- VERB_CREATE, OBJECT_TEST_PROJECT, "n", KEY_NAME,
+ VERB_CREATE, OBJECT_TEST_PROJECT, "n", KEY_NAME, //$NON-NLS-1$
"Project name", null);
define(Mode.STRING, true,
- VERB_CREATE, OBJECT_TEST_PROJECT, "m", KEY_MAIN_PROJECT,
+ VERB_CREATE, OBJECT_TEST_PROJECT, "m", KEY_MAIN_PROJECT, //$NON-NLS-1$
"Path to directory of the app under test, relative to the test project directory",
null);
// --- create lib-project ---
define(Mode.STRING, true,
- VERB_CREATE, OBJECT_LIB_PROJECT,
- "p", KEY_PATH,
+ VERB_CREATE, OBJECT_LIB_PROJECT, "p", KEY_PATH, //$NON-NLS-1$
"The new project's directory", null);
define(Mode.STRING, true,
- VERB_CREATE, OBJECT_LIB_PROJECT, "t", KEY_TARGET_ID,
+ VERB_CREATE, OBJECT_LIB_PROJECT, "t", KEY_TARGET_ID, //$NON-NLS-1$
"Target ID of the new project", null);
define(Mode.STRING, false,
- VERB_CREATE, OBJECT_LIB_PROJECT, "n", KEY_NAME,
+ VERB_CREATE, OBJECT_LIB_PROJECT, "n", KEY_NAME, //$NON-NLS-1$
"Project name", null);
define(Mode.STRING, true,
- VERB_CREATE, OBJECT_LIB_PROJECT, "k", KEY_PACKAGE,
+ VERB_CREATE, OBJECT_LIB_PROJECT, "k", KEY_PACKAGE, //$NON-NLS-1$
"Android package name for the library", null);
// --- create export-project ---
@@ -324,75 +346,63 @@ class SdkCommandLine extends CommandLineProcessor {
* disabled until the feature is officially supported.
define(Mode.STRING, true,
- VERB_CREATE, OBJECT_EXPORT_PROJECT,
- "p", KEY_PATH,
+ VERB_CREATE, OBJECT_EXPORT_PROJECT, "p", KEY_PATH, //$NON-NLS-1$
"Location path of new project", null);
define(Mode.STRING, false,
- VERB_CREATE, OBJECT_EXPORT_PROJECT, "n", KEY_NAME,
+ VERB_CREATE, OBJECT_EXPORT_PROJECT, "n", KEY_NAME, //$NON-NLS-1$
"Project name", null);
define(Mode.STRING, true,
- VERB_CREATE, OBJECT_EXPORT_PROJECT, "k", KEY_PACKAGE,
+ VERB_CREATE, OBJECT_EXPORT_PROJECT, "k", KEY_PACKAGE, //$NON-NLS-1$
"Package name", null);
*/
// --- update project ---
define(Mode.STRING, true,
- VERB_UPDATE, OBJECT_PROJECT,
- "p", KEY_PATH,
+ VERB_UPDATE, OBJECT_PROJECT, "p", KEY_PATH, //$NON-NLS-1$
"The project's directory", null);
define(Mode.STRING, false,
- VERB_UPDATE, OBJECT_PROJECT,
- "t", KEY_TARGET_ID,
+ VERB_UPDATE, OBJECT_PROJECT, "t", KEY_TARGET_ID, //$NON-NLS-1$
"Target ID to set for the project", null);
define(Mode.STRING, false,
- VERB_UPDATE, OBJECT_PROJECT,
- "n", KEY_NAME,
+ VERB_UPDATE, OBJECT_PROJECT, "n", KEY_NAME, //$NON-NLS-1$
"Project name", null);
define(Mode.BOOLEAN, false,
- VERB_UPDATE, OBJECT_PROJECT,
- "s", KEY_SUBPROJECTS,
+ VERB_UPDATE, OBJECT_PROJECT, "s", KEY_SUBPROJECTS, //$NON-NLS-1$
"Also updates any projects in sub-folders, such as test projects.", false);
define(Mode.STRING, false,
- VERB_UPDATE, OBJECT_PROJECT,
- "l", KEY_LIBRARY,
+ VERB_UPDATE, OBJECT_PROJECT, "l", KEY_LIBRARY, //$NON-NLS-1$
"Directory of an Android library to add, relative to this project's directory",
null);
// --- update test project ---
define(Mode.STRING, true,
- VERB_UPDATE, OBJECT_TEST_PROJECT,
- "p", KEY_PATH,
+ VERB_UPDATE, OBJECT_TEST_PROJECT, "p", KEY_PATH, //$NON-NLS-1$
"The project's directory", null);
define(Mode.STRING, true,
- VERB_UPDATE, OBJECT_TEST_PROJECT,
- "m", KEY_MAIN_PROJECT,
+ VERB_UPDATE, OBJECT_TEST_PROJECT, "m", KEY_MAIN_PROJECT, //$NON-NLS-1$
"Directory of the app under test, relative to the test project directory", null);
// --- update lib project ---
define(Mode.STRING, true,
- VERB_UPDATE, OBJECT_LIB_PROJECT,
- "p", KEY_PATH,
+ VERB_UPDATE, OBJECT_LIB_PROJECT, "p", KEY_PATH, //$NON-NLS-1$
"The project's directory", null);
define(Mode.STRING, false,
- VERB_UPDATE, OBJECT_LIB_PROJECT,
- "t", KEY_TARGET_ID,
+ VERB_UPDATE, OBJECT_LIB_PROJECT, "t", KEY_TARGET_ID, //$NON-NLS-1$
"Target ID to set for the project", null);
// --- update export project ---
/*
* disabled until the feature is officially supported.
define(Mode.STRING, true,
- VERB_UPDATE, OBJECT_EXPORT_PROJECT,
- "p", KEY_PATH,
+ VERB_UPDATE, OBJECT_EXPORT_PROJECT, "p", KEY_PATH, //$NON-NLS-1$
"Location path of the project", null);
define(Mode.STRING, false,
- VERB_UPDATE, OBJECT_EXPORT_PROJECT,
- "n", KEY_NAME,
+ VERB_UPDATE, OBJECT_EXPORT_PROJECT, "n", KEY_NAME, //$NON-NLS-1$
"Project name", null);
define(Mode.BOOLEAN, false,
- VERB_UPDATE, OBJECT_EXPORT_PROJECT, "f", KEY_FORCE,
+ VERB_UPDATE, OBJECT_EXPORT_PROJECT, "f", KEY_FORCE, //$NON-NLS-1$
"Force replacing the build.xml file", false);
*/
}
@@ -527,4 +537,16 @@ class SdkCommandLine extends CommandLineProcessor {
public String getParamProxyPort() {
return ((String) getValue(null, null, KEY_PROXY_PORT));
}
+
+ // -- some helpers for list avds and list targets flags
+
+ /** Helper to retrieve the --compact value. */
+ public boolean getFlagCompact() {
+ return ((Boolean) getValue(null, null, KEY_COMPACT)).booleanValue();
+ }
+
+ /** Helper to retrieve the --null value. */
+ public boolean getFlagEolNull() {
+ return ((Boolean) getValue(null, null, KEY_EOL_NULL)).booleanValue();
+ }
}
diff --git a/sdkmanager/app/tests/com/android/sdkmanager/AvdManagerTest.java b/sdkmanager/app/tests/com/android/sdkmanager/AvdManagerTest.java
index 9579bf5..a5a8289 100644
--- a/sdkmanager/app/tests/com/android/sdkmanager/AvdManagerTest.java
+++ b/sdkmanager/app/tests/com/android/sdkmanager/AvdManagerTest.java
@@ -16,49 +16,36 @@
package com.android.sdkmanager;
-import static java.io.File.createTempFile;
-
import com.android.io.FileWrapper;
import com.android.sdklib.IAndroidTarget;
-import com.android.sdklib.SdkManager;
-import com.android.sdklib.internal.avd.AvdManager;
-import com.android.sdklib.internal.project.ProjectProperties;
-import com.android.sdklib.mock.MockLog;
import com.android.sdklib.SdkConstants;
+import com.android.sdklib.internal.avd.AvdInfo;
+import com.android.sdklib.internal.project.ProjectProperties;
import java.io.File;
import java.util.Map;
-import junit.framework.TestCase;
-
-public class AvdManagerTest extends TestCase {
+public class AvdManagerTest extends SdkManagerTestCase {
- private AvdManager mAvdManager;
- private SdkManager mSdkManager;
- private MockLog mLog;
- private File mFakeSdk;
- private File mAvdFolder;
private IAndroidTarget mTarget;
+ private File mAvdFolder;
@Override
public void setUp() throws Exception {
- mLog = new MockLog();
- mFakeSdk = SdkManagerTestUtil.makeFakeSdk(createTempFile(this.getClass().getSimpleName(), null));
- mSdkManager = SdkManager.createManager(mFakeSdk.getAbsolutePath(), mLog);
- assertNotNull("sdkManager location was invalid", mSdkManager);
+ super.setUp();
- mAvdManager = new AvdManager(mSdkManager, mLog);
- mAvdFolder = new File(mFakeSdk, "avdData");
- mTarget = mSdkManager.getTargets()[0];
+ mTarget = getSdkManager().getTargets()[0];
+ mAvdFolder = AvdInfo.getDefaultAvdFolder(getAvdManager(), getName());
}
@Override
public void tearDown() throws Exception {
- SdkManagerTestUtil.deleteDir(mFakeSdk);
+ super.tearDown();
}
public void testCreateAvdWithoutSnapshot() {
- mAvdManager.createAvd(
+
+ getAvdManager().createAvd(
mAvdFolder,
this.getName(),
mTarget,
@@ -69,17 +56,17 @@ public class AvdManagerTest extends TestCase {
false, // createSnapshot
false, // removePrevious
false, // editExisting
- mLog);
+ getLog());
assertEquals("[P Created AVD '" + this.getName() + "' based on Android 0.0, ARM (armeabi) processor\n]",
- mLog.toString());
+ getLog().toString());
assertTrue("Expected config.ini in " + mAvdFolder,
new File(mAvdFolder, "config.ini").exists());
Map<String, String> map = ProjectProperties.parsePropertyFile(
- new FileWrapper(mAvdFolder, "config.ini"), mLog);
+ new FileWrapper(mAvdFolder, "config.ini"), getLog());
assertEquals("HVGA", map.get("skin.name"));
- assertEquals("platforms/v0_0/skins/HVGA", map.get("skin.path"));
- assertEquals("platforms/v0_0/images/", map.get("image.sysdir.1"));
+ assertEquals("platforms/v0_0/skins/HVGA", map.get("skin.path").replace(File.separatorChar, '/'));
+ assertEquals("platforms/v0_0/images/", map.get("image.sysdir.1").replace(File.separatorChar, '/'));
assertEquals(null, map.get("snapshot.present"));
assertTrue("Expected userdata.img in " + mAvdFolder,
new File(mAvdFolder, "userdata.img").exists());
@@ -89,7 +76,7 @@ public class AvdManagerTest extends TestCase {
public void testCreateAvdWithSnapshot() {
- mAvdManager.createAvd(
+ getAvdManager().createAvd(
mAvdFolder,
this.getName(),
mTarget,
@@ -100,14 +87,14 @@ public class AvdManagerTest extends TestCase {
true, // createSnapshot
false, // removePrevious
false, // editExisting
- mLog);
+ getLog());
assertEquals("[P Created AVD '" + this.getName() + "' based on Android 0.0, ARM (armeabi) processor\n]",
- mLog.toString());
+ getLog().toString());
assertTrue("Expected snapshots.img in " + mAvdFolder,
new File(mAvdFolder, "snapshots.img").exists());
Map<String, String> map = ProjectProperties.parsePropertyFile(
- new FileWrapper(mAvdFolder, "config.ini"), mLog);
+ new FileWrapper(mAvdFolder, "config.ini"), getLog());
assertEquals("true", map.get("snapshot.present"));
}
}
diff --git a/sdkmanager/app/tests/com/android/sdkmanager/MainTest.java b/sdkmanager/app/tests/com/android/sdkmanager/MainTest.java
index 3acb01a..4a17e32 100644
--- a/sdkmanager/app/tests/com/android/sdkmanager/MainTest.java
+++ b/sdkmanager/app/tests/com/android/sdkmanager/MainTest.java
@@ -19,9 +19,7 @@ package com.android.sdkmanager;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.SdkConstants;
-import com.android.sdklib.SdkManager;
-import com.android.sdklib.internal.avd.AvdManager;
-import com.android.sdklib.mock.MockLog;
+import com.android.sdklib.internal.avd.AvdInfo;
import com.android.sdklib.repository.SdkAddonConstants;
import com.android.sdklib.repository.SdkRepoConstants;
import com.android.util.Pair;
@@ -32,49 +30,36 @@ import java.util.Arrays;
import java.util.Set;
import java.util.TreeSet;
-import junit.framework.TestCase;
+public class MainTest extends SdkManagerTestCase {
-public class MainTest extends TestCase {
-
- private File mFakeSdk;
- private MockLog mLog;
- private SdkManager mSdkManager;
- private AvdManager mAvdManager;
- private File mAvdFolder;
private IAndroidTarget mTarget;
- private File fakeSdkDir;
+ private File mAvdFolder;
@Override
public void setUp() throws Exception {
- mLog = new MockLog();
- fakeSdkDir = File.createTempFile(
- this.getClass().getSimpleName() + '_' + this.getName(), null);
- mFakeSdk = SdkManagerTestUtil.makeFakeSdk(fakeSdkDir);
- mSdkManager = SdkManager.createManager(mFakeSdk.getAbsolutePath(), mLog);
- assertNotNull("sdkManager location was invalid", mSdkManager);
-
- mAvdManager = new AvdManager(mSdkManager, mLog);
- mAvdFolder = new File(mFakeSdk, "avdData");
- mTarget = mSdkManager.getTargets()[0];
+ super.setUp();
+
+ mTarget = getSdkManager().getTargets()[0];
+ mAvdFolder = AvdInfo.getDefaultAvdFolder(getAvdManager(), getName());
}
@Override
public void tearDown() throws Exception {
- SdkManagerTestUtil.deleteDir(mFakeSdk);
+ super.tearDown();
}
public void testDisplayEmptyAvdList() {
Main main = new Main();
- main.setLogger(mLog);
- mLog.clear();
- main.displayAvdList(mAvdManager);
- assertEquals("P Available Android Virtual Devices:\n", mLog.toString());
+ main.setLogger(getLog());
+ getLog().clear();
+ main.displayAvdList(getAvdManager());
+ assertEquals("[P Available Android Virtual Devices:\n]", getLog().toString());
}
public void testDisplayAvdListOfOneNonSnapshot() {
Main main = new Main();
- main.setLogger(mLog);
- mAvdManager.createAvd(
+ main.setLogger(getLog());
+ getAvdManager().createAvd(
mAvdFolder,
this.getName(),
mTarget,
@@ -85,10 +70,10 @@ public class MainTest extends TestCase {
false, // createSnapshot
false, // removePrevious
false, // editExisting
- mLog);
+ getLog());
- mLog.clear();
- main.displayAvdList(mAvdManager);
+ getLog().clear();
+ main.displayAvdList(getAvdManager());
assertEquals(
"[P Available Android Virtual Devices:\n"
+ ", P Name: " + this.getName() + "\n"
@@ -96,14 +81,14 @@ public class MainTest extends TestCase {
+ ", P Target: Android 0.0 (API level 0)\n"
+ ", P Skin: HVGA\n"
+ "]",
- mLog.toString());
+ getLog().toString());
}
public void testDisplayAvdListOfOneSnapshot() {
Main main = new Main();
- main.setLogger(mLog);
+ main.setLogger(getLog());
- mAvdManager.createAvd(
+ getAvdManager().createAvd(
mAvdFolder,
this.getName(),
mTarget,
@@ -114,10 +99,10 @@ public class MainTest extends TestCase {
true, // createSnapshot
false, // removePrevious
false, // editExisting
- mLog);
+ getLog());
- mLog.clear();
- main.displayAvdList(mAvdManager);
+ getLog().clear();
+ main.displayAvdList(getAvdManager());
assertEquals(
"[P Available Android Virtual Devices:\n"
+ ", P Name: " + this.getName() + "\n"
@@ -126,7 +111,7 @@ public class MainTest extends TestCase {
+ ", P Skin: HVGA\n"
+ ", P Snapshot: true\n"
+ "]",
- mLog.toString());
+ getLog().toString());
}
public void testCheckFilterValues() {
@@ -178,7 +163,7 @@ public class MainTest extends TestCase {
// Finally check that checkFilterValues accepts all these values, one by one.
Main main = new Main();
- main.setLogger(mLog);
+ main.setLogger(getLog());
for (int step = 0; step < 3; step++) {
for (String value : expectedValues) {
diff --git a/sdkmanager/app/tests/com/android/sdkmanager/SdkManagerTestCase.java b/sdkmanager/app/tests/com/android/sdkmanager/SdkManagerTestCase.java
new file mode 100755
index 0000000..9fdd852
--- /dev/null
+++ b/sdkmanager/app/tests/com/android/sdkmanager/SdkManagerTestCase.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.sdkmanager;
+
+
+import com.android.prefs.AndroidLocation;
+import com.android.prefs.AndroidLocation.AndroidLocationException;
+import com.android.sdklib.ISdkLog;
+import com.android.sdklib.SdkConstants;
+import com.android.sdklib.SdkManager;
+import com.android.sdklib.internal.avd.AvdManager;
+import com.android.sdklib.mock.MockLog;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+
+import junit.framework.TestCase;
+
+/**
+ * Test case that allocates a temporary SDK, a temporary AVD base folder
+ * with an SdkManager and an AvdManager that points to them.
+ */
+public abstract class SdkManagerTestCase extends TestCase {
+
+ private File mFakeSdk;
+ private MockLog mLog;
+ private SdkManager mSdkManager;
+ private TmpAvdManager mAvdManager;
+
+ /** Returns the {@link MockLog} for this test case. */
+ public MockLog getLog() {
+ return mLog;
+ }
+
+ /** Returns the {@link SdkManager} for this test case. */
+ public SdkManager getSdkManager() {
+ return mSdkManager;
+ }
+
+ /** Returns the {@link AvdManager} for this test case. */
+ public TmpAvdManager getAvdManager() {
+ return mAvdManager;
+ }
+
+ /**
+ * Sets up a {@link MockLog}, a fake SDK in a temporary directory
+ * and an AVD Manager pointing to an initially-empty AVD directory.
+ */
+ @Override
+ public void setUp() throws Exception {
+ mLog = new MockLog();
+ mFakeSdk = makeFakeSdk();
+ mSdkManager = SdkManager.createManager(mFakeSdk.getAbsolutePath(), mLog);
+ assertNotNull("SdkManager location was invalid", mSdkManager);
+
+ mAvdManager = new TmpAvdManager(mSdkManager, mLog);
+ }
+
+ /**
+ * Removes the temporary SDK and AVD directories.
+ */
+ @Override
+ public void tearDown() throws Exception {
+ deleteDir(mFakeSdk);
+ }
+
+ /**
+ * An {@link AvdManager} that uses a temporary directory
+ * located <em>inside</em> the SDK directory for testing.
+ * The AVD list should be initially empty.
+ */
+ protected static class TmpAvdManager extends AvdManager {
+
+ /*
+ * Implementation detail:
+ * - When the super.AvdManager constructor is invoked, it will invoke
+ * the buildAvdFilesList() to fill the initial AVD list, which will in
+ * turn call getBaseAvdFolder().
+ * - That's why mTmpAvdRoot is initialized in getAvdRoot() rather than
+ * in the constructor, since we can't initialize fields before the super()
+ * call.
+ */
+
+ /**
+ * AVD Root, initialized "lazily" when the AVD root is first requested.
+ */
+ private File mTmpAvdRoot;
+
+ public TmpAvdManager(SdkManager sdkManager, ISdkLog log) throws AndroidLocationException {
+ super(sdkManager, log);
+ }
+
+ @Override
+ public String getBaseAvdFolder() throws AndroidLocationException {
+ if (mTmpAvdRoot == null) {
+ mTmpAvdRoot = new File(getSdkManager().getLocation(), "tmp_avds");
+ mTmpAvdRoot.mkdirs();
+ }
+ return mTmpAvdRoot.getAbsolutePath();
+ }
+ }
+
+ /**
+ * Build enough of a skeleton SDK to make the tests pass.
+ * <p/>
+ * Ideally this wouldn't touch the file system but the current
+ * structure of the SdkManager and AvdManager makes this difficult.
+ *
+ * @return Path to the temporary SDK root
+ * @throws IOException
+ */
+ private File makeFakeSdk() throws IOException {
+
+ File tmpFile = File.createTempFile(
+ this.getClass().getSimpleName() + '_' + this.getName(), null);
+ tmpFile.delete();
+ tmpFile.mkdirs();
+
+ AndroidLocation.resetFolder();
+ System.setProperty("user.home", tmpFile.getAbsolutePath());
+ File addonsDir = new File(tmpFile, SdkConstants.FD_ADDONS);
+ addonsDir.mkdir();
+ File toolsLibEmuDir = new File(tmpFile, SdkConstants.OS_SDK_TOOLS_LIB_FOLDER + "emulator");
+ toolsLibEmuDir.mkdirs();
+ new File(toolsLibEmuDir, "snapshots.img").createNewFile();
+ File platformsDir = new File(tmpFile, SdkConstants.FD_PLATFORMS);
+
+ // Creating a fake target here on down
+ File targetDir = new File(platformsDir, "v0_0");
+ targetDir.mkdirs();
+ new File(targetDir, SdkConstants.FN_FRAMEWORK_LIBRARY).createNewFile();
+ new File(targetDir, SdkConstants.FN_FRAMEWORK_AIDL).createNewFile();
+ new File(targetDir, SdkConstants.FN_SOURCE_PROP).createNewFile();
+ File buildProp = new File(targetDir, SdkConstants.FN_BUILD_PROP);
+ FileWriter out = new FileWriter(buildProp);
+ out.write(SdkManager.PROP_VERSION_RELEASE + "=0.0\n");
+ out.write(SdkManager.PROP_VERSION_SDK + "=0\n");
+ out.write(SdkManager.PROP_VERSION_CODENAME + "=REL\n");
+ out.close();
+ File imagesDir = new File(targetDir, "images");
+ imagesDir.mkdirs();
+ new File(imagesDir, "userdata.img").createNewFile();
+ File skinsDir = new File(targetDir, "skins");
+ File hvgaDir = new File(skinsDir, "HVGA");
+ hvgaDir.mkdirs();
+ return tmpFile;
+ }
+
+ /**
+ * Recursive delete directory. Mostly for fake SDKs.
+ *
+ * @param root directory to delete
+ */
+ private void deleteDir(File root) {
+ if (root.exists()) {
+ for (File file : root.listFiles()) {
+ if (file.isDirectory()) {
+ deleteDir(file);
+ } else {
+ file.delete();
+ }
+ }
+ root.delete();
+ }
+ }
+
+}
diff --git a/sdkmanager/app/tests/com/android/sdkmanager/SdkManagerTestUtil.java b/sdkmanager/app/tests/com/android/sdkmanager/SdkManagerTestUtil.java
deleted file mode 100644
index 96efb5c..0000000
--- a/sdkmanager/app/tests/com/android/sdkmanager/SdkManagerTestUtil.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.sdkmanager;
-
-import com.android.prefs.AndroidLocation;
-import com.android.sdklib.SdkConstants;
-import com.android.sdklib.SdkManager;
-
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-
-public class SdkManagerTestUtil {
- /**
- * Build enough of a skeleton SDK to make the tests pass.
- *<p>
- * Ideally this wouldn't touch the file system, but I'm not inclined to
- * fiddle around with mock file systems just at the moment.
- *
- * @return an sdk manager to a fake sdk
- * @throws IOException
- */
- public static File makeFakeSdk(File fakeSdk) throws IOException {
- fakeSdk.delete();
- fakeSdk.mkdirs();
- AndroidLocation.resetFolder();
- System.setProperty("user.home", fakeSdk.getAbsolutePath());
- File addonsDir = new File(fakeSdk, SdkConstants.FD_ADDONS);
- addonsDir.mkdir();
- File toolsLibEmuDir = new File(fakeSdk, SdkConstants.OS_SDK_TOOLS_LIB_FOLDER + "emulator");
- toolsLibEmuDir.mkdirs();
- new File(toolsLibEmuDir, "snapshots.img").createNewFile();
- File platformsDir = new File(fakeSdk, SdkConstants.FD_PLATFORMS);
-
- // Creating a fake target here on down
- File targetDir = new File(platformsDir, "v0_0");
- targetDir.mkdirs();
- new File(targetDir, SdkConstants.FN_FRAMEWORK_LIBRARY).createNewFile();
- new File(targetDir, SdkConstants.FN_FRAMEWORK_AIDL).createNewFile();
- new File(targetDir, SdkConstants.FN_SOURCE_PROP).createNewFile();
- File buildProp = new File(targetDir, SdkConstants.FN_BUILD_PROP);
- FileWriter out = new FileWriter(buildProp);
- out.write(SdkManager.PROP_VERSION_RELEASE + "=0.0\n");
- out.write(SdkManager.PROP_VERSION_SDK + "=0\n");
- out.write(SdkManager.PROP_VERSION_CODENAME + "=REL\n");
- out.close();
- File imagesDir = new File(targetDir, "images");
- imagesDir.mkdirs();
- new File(imagesDir, "userdata.img").createNewFile();
- File skinsDir = new File(targetDir, "skins");
- File hvgaDir = new File(skinsDir, "HVGA");
- hvgaDir.mkdirs();
- return fakeSdk;
- }
-
- /**
- * Recursive delete directory. Mostly for fake SDKs.
- *
- * @param root directory to delete
- */
- public static void deleteDir(File root) {
- if (root.exists()) {
- for (File file : root.listFiles()) {
- if (file.isDirectory()) {
- deleteDir(file);
- } else {
- file.delete();
- }
- }
- root.delete();
- }
- }
-
-}
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdInfo.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdInfo.java
new file mode 100755
index 0000000..81ffa5d
--- /dev/null
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdInfo.java
@@ -0,0 +1,334 @@
+/*
+ * Copyright (C) 2008 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.avd;
+
+import com.android.prefs.AndroidLocation.AndroidLocationException;
+import com.android.sdklib.IAndroidTarget;
+import com.android.sdklib.SdkConstants;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * An immutable structure describing an Android Virtual Device.
+ */
+public final class AvdInfo implements Comparable<AvdInfo> {
+
+ /**
+ * Status for an {@link AvdInfo}. Indicates whether or not this AVD is valid.
+ */
+ public static enum AvdStatus {
+ /** No error */
+ OK,
+ /** Missing 'path' property in the ini file */
+ ERROR_PATH,
+ /** Missing config.ini file in the AVD data folder */
+ ERROR_CONFIG,
+ /** Missing 'target' property in the ini file */
+ ERROR_TARGET_HASH,
+ /** Target was not resolved from its hash */
+ ERROR_TARGET,
+ /** Unable to parse config.ini */
+ ERROR_PROPERTIES,
+ /** System Image folder in config.ini doesn't exist */
+ ERROR_IMAGE_DIR;
+ }
+
+ private final String mName;
+ private final File mIniFile;
+ private final String mFolderPath;
+ private final String mTargetHash;
+ private final IAndroidTarget mTarget;
+ private final String mAbiType;
+ private final Map<String, String> mProperties;
+ private final AvdStatus mStatus;
+
+ /**
+ * Creates a new valid AVD info. Values are immutable.
+ * <p/>
+ * Such an AVD is available and can be used.
+ * The error string is set to null.
+ *
+ * @param name The name of the AVD (for display or reference)
+ * @param iniFile The path to the config.ini file
+ * @param folderPath The path to the data directory
+ * @param targetHash the target hash
+ * @param target The target. Can be null, if the target was not resolved.
+ * @param abiType Name of the abi.
+ * @param properties The property map. Cannot be null.
+ */
+ public AvdInfo(String name,
+ File iniFile,
+ String folderPath,
+ String targetHash,
+ IAndroidTarget target,
+ String abiType,
+ Map<String, String> properties) {
+ this(name, iniFile, folderPath, targetHash, target, abiType, properties, AvdStatus.OK);
+ }
+
+ /**
+ * Creates a new <em>invalid</em> AVD info. Values are immutable.
+ * <p/>
+ * Such an AVD is not complete and cannot be used.
+ * The error string must be non-null.
+ *
+ * @param name The name of the AVD (for display or reference)
+ * @param iniFile The path to the config.ini file
+ * @param folderPath The path to the data directory
+ * @param targetHash the target hash
+ * @param target The target. Can be null, if the target was not resolved.
+ * @param abiType Name of the abi.
+ * @param properties The property map. Can be null.
+ * @param status The {@link AvdStatus} of this AVD. Cannot be null.
+ */
+ public AvdInfo(String name,
+ File iniFile,
+ String folderPath,
+ String targetHash,
+ IAndroidTarget target,
+ String abiType,
+ Map<String, String> properties,
+ AvdStatus status) {
+ mName = name;
+ mIniFile = iniFile;
+ mFolderPath = folderPath;
+ mTargetHash = targetHash;
+ mTarget = target;
+ mAbiType = abiType;
+ mProperties = properties == null ? null : Collections.unmodifiableMap(properties);
+ mStatus = status;
+ }
+
+ /** Returns the name of the AVD. */
+ public String getName() {
+ return mName;
+ }
+
+ /** Returns the path of the AVD data directory. */
+ public String getDataFolderPath() {
+ return mFolderPath;
+ }
+
+ /** Returns the processor type of the AVD. */
+ public String getAbiType() {
+ return mAbiType;
+ }
+
+ /** Convenience function to return a more user friendly name of the abi type. */
+ public static String getPrettyAbiType(String raw) {
+ String s = null;
+ if (raw.equalsIgnoreCase(SdkConstants.ABI_ARMEABI)) {
+ s = "ARM (" + SdkConstants.ABI_ARMEABI + ")";
+ }
+ else if (raw.equalsIgnoreCase(SdkConstants.ABI_INTEL_ATOM)) {
+ s = "Intel Atom (" + SdkConstants.ABI_INTEL_ATOM + ")";
+ }
+ else {
+ s = raw + " (" + raw + ")";
+ }
+ return s;
+ }
+
+ /**
+ * Returns the emulator executable path
+ * @param sdkPath path of the sdk
+ * @return path of the emulator executable
+ */
+ public String getEmulatorPath(String sdkPath) {
+ String path = sdkPath + SdkConstants.OS_SDK_TOOLS_FOLDER;
+
+ // Start with base name of the emulator
+ path = path + SdkConstants.FN_EMULATOR;
+
+ // If not using ARM, add processor type to emulator command line
+ boolean useAbi = !getAbiType().equalsIgnoreCase(SdkConstants.ABI_ARMEABI);
+
+ if (useAbi) {
+ path = path + "-" + getAbiType(); //$NON-NLS-1$
+ }
+ // Add OS appropriate emulator extension (e.g., .exe on windows)
+ path = path + SdkConstants.FN_EMULATOR_EXTENSION;
+
+ // HACK: The AVD manager should look for "emulator" or for "emulator-abi" (if not arm).
+ // However this is a transition period and we don't have that unified "emulator" binary
+ // in AOSP so if we can't find the generic one, look for an abi-specific one with the
+ // special case that the armeabi one is actually named emulator-arm.
+ // TODO remove this kludge once no longer necessary.
+ if (!useAbi && !(new File(path).isFile())) {
+ path = sdkPath + SdkConstants.OS_SDK_TOOLS_FOLDER;
+ path = path + SdkConstants.FN_EMULATOR;
+ path = path + "-" //$NON-NLS-1$
+ + getAbiType().replace(SdkConstants.ABI_ARMEABI, "arm"); //$NON-NLS-1$
+ path = path + SdkConstants.FN_EMULATOR_EXTENSION;
+ }
+
+ return path;
+ }
+
+ /**
+ * Returns the target hash string.
+ */
+ public String getTargetHash() {
+ return mTargetHash;
+ }
+
+ /** Returns the target of the AVD, or <code>null</code> if it has not been resolved. */
+ public IAndroidTarget getTarget() {
+ return mTarget;
+ }
+
+ /** Returns the {@link AvdStatus} of the receiver. */
+ public AvdStatus getStatus() {
+ return mStatus;
+ }
+
+ /**
+ * Helper method that returns the default AVD folder that would be used for a given
+ * AVD name <em>if and only if</em> the AVD was created with the default choice.
+ * <p/>
+ * Callers must NOT use this to "guess" the actual folder from an actual AVD since
+ * the purpose of the AVD .ini file is to be able to change this folder. Callers
+ * should however use this to create a new {@link AvdInfo} to setup its data folder
+ * to the default.
+ * <p/>
+ * The default is {@code getDefaultAvdFolder()/avdname.avd/}.
+ * <p/>
+ * For an actual existing AVD, callers must use {@link #getDataFolderPath()} instead.
+ *
+ * @param manager The AVD Manager, used to get the AVD storage path.
+ * @param avdName The name of the desired AVD.
+ * @throws AndroidLocationException if there's a problem getting android root directory.
+ */
+ public static File getDefaultAvdFolder(AvdManager manager, String avdName)
+ throws AndroidLocationException {
+ return new File(manager.getBaseAvdFolder(),
+ avdName + AvdManager.AVD_FOLDER_EXTENSION);
+ }
+
+ /**
+ * Helper method that returns the .ini {@link File} for a given AVD name.
+ * <p/>
+ * The default is {@code getDefaultAvdFolder()/avdname.ini}.
+ *
+ * @param manager The AVD Manager, used to get the AVD storage path.
+ * @param avdName The name of the desired AVD.
+ * @throws AndroidLocationException if there's a problem getting android root directory.
+ */
+ public static File getDefaultIniFile(AvdManager manager, String avdName)
+ throws AndroidLocationException {
+ String avdRoot = manager.getBaseAvdFolder();
+ return new File(avdRoot, avdName + AvdManager.INI_EXTENSION);
+ }
+
+ /**
+ * Returns the .ini {@link File} for this AVD.
+ */
+ public File getIniFile() {
+ return mIniFile;
+ }
+
+ /**
+ * Helper method that returns the Config {@link File} for a given AVD name.
+ */
+ public static File getConfigFile(String path) {
+ return new File(path, AvdManager.CONFIG_INI);
+ }
+
+ /**
+ * Returns the Config {@link File} for this AVD.
+ */
+ public File getConfigFile() {
+ return getConfigFile(mFolderPath);
+ }
+
+ /**
+ * Returns an unmodifiable map of properties for the AVD. This can be null.
+ */
+ public Map<String, String> getProperties() {
+ return mProperties;
+ }
+
+ /**
+ * Returns the error message for the AVD or <code>null</code> if {@link #getStatus()}
+ * returns {@link AvdStatus#OK}
+ */
+ public String getErrorMessage() {
+ switch (mStatus) {
+ case ERROR_PATH:
+ return String.format("Missing AVD 'path' property in %1$s", getIniFile());
+ case ERROR_CONFIG:
+ return String.format("Missing config.ini file in %1$s", mFolderPath);
+ case ERROR_TARGET_HASH:
+ return String.format("Missing 'target' property in %1$s", getIniFile());
+ case ERROR_TARGET:
+ return String.format("Unknown target '%1$s' in %2$s",
+ mTargetHash, getIniFile());
+ case ERROR_PROPERTIES:
+ return String.format("Failed to parse properties from %1$s",
+ getConfigFile());
+ case ERROR_IMAGE_DIR:
+ return String.format(
+ "Invalid value in image.sysdir. Run 'android update avd -n %1$s'",
+ mName);
+ case OK:
+ assert false;
+ return null;
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns whether an emulator is currently running the AVD.
+ */
+ public boolean isRunning() {
+ File f = new File(mFolderPath, "userdata-qemu.img.lock"); //$NON-NLS-1$
+ return f.isFile();
+ }
+
+ /**
+ * Compares this object with the specified object for order. Returns a
+ * negative integer, zero, or a positive integer as this object is less
+ * than, equal to, or greater than the specified object.
+ *
+ * @param o the Object to be compared.
+ * @return a negative integer, zero, or a positive integer as this object is
+ * less than, equal to, or greater than the specified object.
+ */
+ public int compareTo(AvdInfo o) {
+ // first handle possible missing targets (if the AVD failed to load for unresolved targets)
+ if (mTarget == null && o != null && o.mTarget == null) {
+ return 0;
+ } if (mTarget == null) {
+ return +1;
+ } else if (o == null || o.mTarget == null) {
+ return -1;
+ }
+
+ // then compare the targets
+ int targetDiff = mTarget.compareTo(o.mTarget);
+
+ if (targetDiff == 0) {
+ // same target? compare on the avd name
+ return mName.compareTo(o.mName);
+ }
+
+ return targetDiff;
+ }
+}
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java
index 627bdb9..c9a3561 100644
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java
@@ -23,7 +23,7 @@ import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.ISdkLog;
import com.android.sdklib.SdkConstants;
import com.android.sdklib.SdkManager;
-import com.android.sdklib.internal.avd.AvdManager.AvdInfo.AvdStatus;
+import com.android.sdklib.internal.avd.AvdInfo.AvdStatus;
import com.android.sdklib.internal.project.ProjectProperties;
import com.android.util.Pair;
@@ -38,7 +38,6 @@ import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
@@ -48,7 +47,7 @@ import java.util.regex.Pattern;
/**
* Android Virtual Device Manager to manage AVDs.
*/
-public final class AvdManager {
+public class AvdManager {
/**
* Exception thrown when something is wrong with a target path.
@@ -132,11 +131,11 @@ public final class AvdManager {
public final static Pattern NUMERIC_SKIN_SIZE = Pattern.compile("([0-9]{2,})x([0-9]{2,})"); //$NON-NLS-1$
private final static String USERDATA_IMG = "userdata.img"; //$NON-NLS-1$
- private final static String CONFIG_INI = "config.ini"; //$NON-NLS-1$
+ final static String CONFIG_INI = "config.ini"; //$NON-NLS-1$
private final static String SDCARD_IMG = "sdcard.img"; //$NON-NLS-1$
private final static String SNAPSHOTS_IMG = "snapshots.img"; //$NON-NLS-1$
- private final static String INI_EXTENSION = ".ini"; //$NON-NLS-1$
+ final static String INI_EXTENSION = ".ini"; //$NON-NLS-1$
private final static Pattern INI_NAME_PATTERN = Pattern.compile("(.+)\\" + //$NON-NLS-1$
INI_EXTENSION + "$", //$NON-NLS-1$
Pattern.CASE_INSENSITIVE);
@@ -192,305 +191,12 @@ public final class AvdManager {
CONFLICT_EXISTING_PATH,
}
- /**
- * An immutable structure describing an Android Virtual Device.
- */
- public static final class AvdInfo implements Comparable<AvdInfo> {
-
- /**
- * Status for an {@link AvdInfo}. Indicates whether or not this AVD is valid.
- */
- public static enum AvdStatus {
- /** No error */
- OK,
- /** Missing 'path' property in the ini file */
- ERROR_PATH,
- /** Missing config.ini file in the AVD data folder */
- ERROR_CONFIG,
- /** Missing 'target' property in the ini file */
- ERROR_TARGET_HASH,
- /** Target was not resolved from its hash */
- ERROR_TARGET,
- /** Unable to parse config.ini */
- ERROR_PROPERTIES,
- /** System Image folder in config.ini doesn't exist */
- ERROR_IMAGE_DIR;
- }
-
- private final String mName;
- private final String mPath;
- private final String mTargetHash;
- private final IAndroidTarget mTarget;
- private final String mAbiType;
- private final Map<String, String> mProperties;
- private final AvdStatus mStatus;
-
- /**
- * Creates a new valid AVD info. Values are immutable.
- * <p/>
- * Such an AVD is available and can be used.
- * The error string is set to null.
- *
- * @param name The name of the AVD (for display or reference)
- * @param path The path to the config.ini file
- * @param targetHash the target hash
- * @param target The target. Can be null, if the target was not resolved.
- * @param abiType Name of the abi.
- * @param properties The property map. Cannot be null.
- */
- public AvdInfo(String name, String path, String targetHash, IAndroidTarget target,
- String abiType, Map<String, String> properties) {
- this(name, path, targetHash, target, abiType, properties, AvdStatus.OK);
- }
-
- /**
- * Creates a new <em>invalid</em> AVD info. Values are immutable.
- * <p/>
- * Such an AVD is not complete and cannot be used.
- * The error string must be non-null.
- *
- * @param name The name of the AVD (for display or reference)
- * @param path The path to the config.ini file
- * @param targetHash the target hash
- * @param target The target. Can be null, if the target was not resolved.
- * @param abiType Name of the abi.
- * @param properties The property map. Can be null.
- * @param status The {@link AvdStatus} of this AVD. Cannot be null.
- */
- public AvdInfo(String name, String path, String targetHash, IAndroidTarget target,
- String abiType, Map<String, String> properties, AvdStatus status) {
- mName = name;
- mPath = path;
- mTargetHash = targetHash;
- mTarget = target;
- mAbiType = abiType;
- mProperties = properties == null ? null : Collections.unmodifiableMap(properties);
- mStatus = status;
- }
-
- /** Returns the name of the AVD. */
- public String getName() {
- return mName;
- }
-
- /** Returns the path of the AVD data directory. */
- public String getPath() {
- return mPath;
- }
-
- /** Returns the processor type of the AVD. */
- public String getAbiType() {
- return mAbiType;
- }
-
- /** Convenience function to return a more user friendly name of the abi type. */
- public static String getPrettyAbiType(String raw) {
- String s = null;
- if (raw.equalsIgnoreCase(SdkConstants.ABI_ARMEABI)) {
- s = "ARM (" + SdkConstants.ABI_ARMEABI + ")";
- }
- else if (raw.equalsIgnoreCase(SdkConstants.ABI_INTEL_ATOM)) {
- s = "Intel Atom (" + SdkConstants.ABI_INTEL_ATOM + ")";
- }
- else {
- s = raw + " (" + raw + ")";
- }
- return s;
- }
-
- /**
- * Returns the emulator executable path
- * @param sdkPath path of the sdk
- * @return path of the emulator executable
- */
- public String getEmulatorPath(String sdkPath) {
- String path = sdkPath + SdkConstants.OS_SDK_TOOLS_FOLDER;
-
- // Start with base name of the emulator
- path = path + SdkConstants.FN_EMULATOR;
-
- // If not using ARM, add processor type to emulator command line
- boolean useAbi = !getAbiType().equalsIgnoreCase(SdkConstants.ABI_ARMEABI);
-
- if (useAbi) {
- path = path + "-" + getAbiType();
- }
- // Add OS appropriate emulator extension (e.g., .exe on windows)
- path = path + SdkConstants.FN_EMULATOR_EXTENSION;
-
- // HACK: The AVD manager should look for "emulator" or for "emulator-abi" (if not arm).
- // However this is a transition period and we don't have that unified "emulator" binary
- // in AOSP so if we can't find the generic one, look for an abi-specific one with the
- // special case that the armeabi one is actually named emulator-arm.
- // TODO remove this kludge once no longer necessary.
- if (!useAbi && !(new File(path).isFile())) {
- path = sdkPath + SdkConstants.OS_SDK_TOOLS_FOLDER;
- path = path + SdkConstants.FN_EMULATOR;
- path = path + "-" + getAbiType().replace(SdkConstants.ABI_ARMEABI, "arm"); //$NON-NLS-1$
- path = path + SdkConstants.FN_EMULATOR_EXTENSION;
- }
-
- return path;
- }
-
- /**
- * Returns the target hash string.
- */
- public String getTargetHash() {
- return mTargetHash;
- }
-
- /** Returns the target of the AVD, or <code>null</code> if it has not been resolved. */
- public IAndroidTarget getTarget() {
- return mTarget;
- }
-
- /** Returns the {@link AvdStatus} of the receiver. */
- public AvdStatus getStatus() {
- return mStatus;
- }
-
- /**
- * Helper method that returns the default AVD folder that would be used for a given
- * AVD name <em>if and only if</em> the AVD was created with the default choice.
- * <p/>
- * Callers must NOT use this to "guess" the actual folder from an actual AVD since
- * the purpose of the AVD .ini file is to be able to change this folder.
- * <p/>
- * For an actual existing AVD, callers must use {@link #getPath()} instead.
- *
- * @throws AndroidLocationException if there's a problem getting android root directory.
- */
- public static File getAvdFolder(String name) throws AndroidLocationException {
- return new File(AndroidLocation.getFolder() + AndroidLocation.FOLDER_AVD,
- name + AvdManager.AVD_FOLDER_EXTENSION);
- }
-
- /**
- * Helper method that returns the .ini {@link File} for a given AVD name.
- * @throws AndroidLocationException if there's a problem getting android root directory.
- */
- public static File getIniFile(String name) throws AndroidLocationException {
- String avdRoot = getBaseAvdFolder();
- return new File(avdRoot, name + INI_EXTENSION);
- }
-
- /**
- * Returns the .ini {@link File} for this AVD.
- * @throws AndroidLocationException if there's a problem getting android root directory.
- */
- public File getIniFile() throws AndroidLocationException {
- return getIniFile(mName);
- }
-
- /**
- * Helper method that returns the Config {@link File} for a given AVD name.
- */
- public static File getConfigFile(String path) {
- return new File(path, CONFIG_INI);
- }
-
- /**
- * Returns the Config {@link File} for this AVD.
- */
- public File getConfigFile() {
- return getConfigFile(mPath);
- }
-
- /**
- * Returns an unmodifiable map of properties for the AVD. This can be null.
- */
- public Map<String, String> getProperties() {
- return mProperties;
- }
-
- /**
- * Returns the error message for the AVD or <code>null</code> if {@link #getStatus()}
- * returns {@link AvdStatus#OK}
- */
- public String getErrorMessage() {
- try {
- switch (mStatus) {
- case ERROR_PATH:
- return String.format("Missing AVD 'path' property in %1$s", getIniFile());
- case ERROR_CONFIG:
- return String.format("Missing config.ini file in %1$s", mPath);
- case ERROR_TARGET_HASH:
- return String.format("Missing 'target' property in %1$s", getIniFile());
- case ERROR_TARGET:
- return String.format("Unknown target '%1$s' in %2$s",
- mTargetHash, getIniFile());
- case ERROR_PROPERTIES:
- return String.format("Failed to parse properties from %1$s",
- getConfigFile());
- case ERROR_IMAGE_DIR:
- return String.format(
- "Invalid value in image.sysdir. Run 'android update avd -n %1$s'",
- mName);
- case OK:
- assert false;
- return null;
- }
- } catch (AndroidLocationException e) {
- return "Unable to get HOME folder.";
- }
-
- return null;
- }
-
- /**
- * Returns whether an emulator is currently running the AVD.
- */
- public boolean isRunning() {
- File f = new File(mPath, "userdata-qemu.img.lock");
- return f.isFile();
- }
-
- /**
- * Compares this object with the specified object for order. Returns a
- * negative integer, zero, or a positive integer as this object is less
- * than, equal to, or greater than the specified object.
- *
- * @param o the Object to be compared.
- * @return a negative integer, zero, or a positive integer as this object is
- * less than, equal to, or greater than the specified object.
- */
- public int compareTo(AvdInfo o) {
- // first handle possible missing targets (if the AVD failed to load for
- // unresolved targets.
- if (mTarget == null) {
- return +1;
- } else if (o.mTarget == null) {
- return -1;
- }
-
- // then compare the targets
- int targetDiff = mTarget.compareTo(o.mTarget);
-
- if (targetDiff == 0) {
- // same target? compare on the avd name
- return mName.compareTo(o.mName);
- }
-
- return targetDiff;
- }
- }
-
private final ArrayList<AvdInfo> mAllAvdList = new ArrayList<AvdInfo>();
private AvdInfo[] mValidAvdList;
private AvdInfo[] mBrokenAvdList;
private final SdkManager mSdkManager;
/**
- * Returns the base folder where AVDs are created.
- *
- * @throws AndroidLocationException
- */
- public static String getBaseAvdFolder() throws AndroidLocationException {
- return AndroidLocation.getFolder() + AndroidLocation.FOLDER_AVD;
- }
-
- /**
* Creates an AVD Manager for a given SDK represented by a {@link SdkManager}.
* @param sdkManager The SDK.
* @param log The log object to receive the log of the initial loading of the AVDs.
@@ -506,6 +212,16 @@ public final class AvdManager {
}
/**
+ * Returns the base folder where AVDs are created.
+ *
+ * @throws AndroidLocationException
+ */
+ public String getBaseAvdFolder() throws AndroidLocationException {
+ assert AndroidLocation.getFolder().endsWith(File.separator);
+ return AndroidLocation.getFolder() + AndroidLocation.FOLDER_AVD;
+ }
+
+ /**
* Returns the {@link SdkManager} associated with the {@link AvdManager}.
*/
public SdkManager getSdkManager() {
@@ -689,12 +405,12 @@ public final class AvdManager {
// Are some existing files/folders in the way of creating this AVD?
try {
- File file = AvdInfo.getIniFile(name);
+ File file = AvdInfo.getDefaultIniFile(this, name);
if (file.exists()) {
return Pair.of(AvdConflict.CONFLICT_EXISTING_PATH, file.getPath());
}
- file = AvdInfo.getAvdFolder(name);
+ file = AvdInfo.getDefaultAvdFolder(this, name);
if (file.exists()) {
return Pair.of(AvdConflict.CONFLICT_EXISTING_PATH, file.getPath());
}
@@ -730,7 +446,9 @@ public final class AvdManager {
* Creates a new AVD. It is expected that there is no existing AVD with this name already.
*
* @param avdFolder the data folder for the AVD. It will be created as needed.
- * @param name the name of the AVD
+ * Unless you want to locate it in a specific directory, the ideal default is
+ * {@code AvdManager.AvdInfo.getAvdFolder}.
+ * @param avdName the name of the AVD
* @param target the target of the AVD
* @param abiType the abi type of the AVD
* @param skinName the name of the skin. Can be null. Must have been verified by caller.
@@ -747,7 +465,7 @@ public final class AvdManager {
*/
public AvdInfo createAvd(
File avdFolder,
- String name,
+ String avdName,
IAndroidTarget target,
String abiType,
String skinName,
@@ -789,7 +507,7 @@ public final class AvdManager {
}
// actually write the ini file
- iniFile = createAvdIniFile(name, avdFolder, target, removePrevious);
+ iniFile = createAvdIniFile(avdName, avdFolder, target, removePrevious);
// writes the userdata.img in it.
String imagePath = target.getImagePath(abiType);
@@ -1004,17 +722,17 @@ public final class AvdManager {
if (target.isPlatform()) {
if (editExisting) {
report.append(String.format("Updated AVD '%1$s' based on %2$s",
- name, target.getName()));
+ avdName, target.getName()));
} else {
report.append(String.format("Created AVD '%1$s' based on %2$s",
- name, target.getName()));
+ avdName, target.getName()));
}
} else {
if (editExisting) {
- report.append(String.format("Updated AVD '%1$s' based on %2$s (%3$s)", name,
+ report.append(String.format("Updated AVD '%1$s' based on %2$s (%3$s)", avdName,
target.getName(), target.getVendor()));
} else {
- report.append(String.format("Created AVD '%1$s' based on %2$s (%3$s)", name,
+ report.append(String.format("Created AVD '%1$s' based on %2$s (%3$s)", avdName,
target.getName(), target.getVendor()));
}
}
@@ -1033,12 +751,14 @@ public final class AvdManager {
log.printf(report.toString());
// create the AvdInfo object, and add it to the list
- AvdInfo newAvdInfo = new AvdInfo(name,
+ AvdInfo newAvdInfo = new AvdInfo(
+ avdName,
+ iniFile,
avdFolder.getAbsolutePath(),
target.hashString(),
target, abiType, values);
- AvdInfo oldAvdInfo = getAvd(name, false /*validAvdOnly*/);
+ AvdInfo oldAvdInfo = getAvd(avdName, false /*validAvdOnly*/);
synchronized (mAllAvdList) {
if (oldAvdInfo != null && (removePrevious || editExisting)) {
@@ -1051,10 +771,11 @@ public final class AvdManager {
if ((removePrevious || editExisting) &&
newAvdInfo != null &&
oldAvdInfo != null &&
- !oldAvdInfo.getPath().equals(newAvdInfo.getPath())) {
- log.warning("Removing previous AVD directory at %s", oldAvdInfo.getPath());
+ !oldAvdInfo.getDataFolderPath().equals(newAvdInfo.getDataFolderPath())) {
+ log.warning("Removing previous AVD directory at %s",
+ oldAvdInfo.getDataFolderPath());
// Remove the old data directory
- File dir = new File(oldAvdInfo.getPath());
+ File dir = new File(oldAvdInfo.getDataFolderPath());
try {
deleteContentOf(dir);
dir.delete();
@@ -1222,7 +943,7 @@ public final class AvdManager {
IAndroidTarget target,
boolean removePrevious)
throws AndroidLocationException, IOException {
- File iniFile = AvdInfo.getIniFile(name);
+ File iniFile = AvdInfo.getDefaultIniFile(this, name);
if (removePrevious) {
if (iniFile.isFile()) {
@@ -1250,7 +971,7 @@ public final class AvdManager {
*/
private File createAvdIniFile(AvdInfo info) throws AndroidLocationException, IOException {
return createAvdIniFile(info.getName(),
- new File(info.getPath()),
+ new File(info.getDataFolderPath()),
info.getTarget(),
false /*removePrevious*/);
}
@@ -1283,7 +1004,7 @@ public final class AvdManager {
}
}
- String path = avdInfo.getPath();
+ String path = avdInfo.getDataFolderPath();
if (path != null) {
f = new File(path);
if (f.exists()) {
@@ -1305,8 +1026,6 @@ public final class AvdManager {
return true;
}
- } catch (AndroidLocationException e) {
- log.error(e, null);
} catch (IOException e) {
log.error(e, null);
} catch (SecurityException e) {
@@ -1333,17 +1052,25 @@ public final class AvdManager {
try {
if (paramFolderPath != null) {
- File f = new File(avdInfo.getPath());
- log.warning("Moving '%1$s' to '%2$s'.", avdInfo.getPath(), paramFolderPath);
+ File f = new File(avdInfo.getDataFolderPath());
+ log.warning("Moving '%1$s' to '%2$s'.",
+ avdInfo.getDataFolderPath(),
+ paramFolderPath);
if (!f.renameTo(new File(paramFolderPath))) {
log.error(null, "Failed to move '%1$s' to '%2$s'.",
- avdInfo.getPath(), paramFolderPath);
+ avdInfo.getDataFolderPath(), paramFolderPath);
return false;
}
// update AVD info
- AvdInfo info = new AvdInfo(avdInfo.getName(), paramFolderPath,
- avdInfo.getTargetHash(), avdInfo.getTarget(), avdInfo.getAbiType(), avdInfo.getProperties());
+ AvdInfo info = new AvdInfo(
+ avdInfo.getName(),
+ avdInfo.getIniFile(),
+ paramFolderPath,
+ avdInfo.getTargetHash(),
+ avdInfo.getTarget(),
+ avdInfo.getAbiType(),
+ avdInfo.getProperties());
replaceAvd(avdInfo, info);
// update the ini file
@@ -1352,7 +1079,7 @@ public final class AvdManager {
if (newName != null) {
File oldIniFile = avdInfo.getIniFile();
- File newIniFile = AvdInfo.getIniFile(newName);
+ File newIniFile = AvdInfo.getDefaultIniFile(this, newName);
log.warning("Moving '%1$s' to '%2$s'.", oldIniFile.getPath(), newIniFile.getPath());
if (!oldIniFile.renameTo(newIniFile)) {
@@ -1362,9 +1089,14 @@ public final class AvdManager {
}
// update AVD info
- AvdInfo info = new AvdInfo(newName, avdInfo.getPath(),
- avdInfo.getTargetHash(), avdInfo.getTarget(),
- avdInfo.getAbiType(), avdInfo.getProperties());
+ AvdInfo info = new AvdInfo(
+ newName,
+ avdInfo.getIniFile(),
+ avdInfo.getDataFolderPath(),
+ avdInfo.getTargetHash(),
+ avdInfo.getTarget(),
+ avdInfo.getAbiType(),
+ avdInfo.getProperties());
replaceAvd(avdInfo, info);
}
@@ -1409,19 +1141,20 @@ public final class AvdManager {
* <p/>
* This lists the $HOME/.android/avd/<name>.ini files.
* Such files are properties file than then indicate where the AVD folder is located.
+ * <p/>
+ * Note: the method is to be considered private. It is made protected so that
+ * unit tests can easily override the AVD root.
*
* @return A new {@link File} array or null. The array might be empty.
* @throws AndroidLocationException if there's a problem getting android root directory.
*/
private File[] buildAvdFilesList() throws AndroidLocationException {
- // get the Android prefs location.
- String avdRoot = AvdManager.getBaseAvdFolder();
+ File folder = new File(getBaseAvdFolder());
// ensure folder validity.
- File folder = new File(avdRoot);
if (folder.isFile()) {
throw new AndroidLocationException(
- String.format("%1$s is not a valid folder.", avdRoot));
+ String.format("%1$s is not a valid folder.", folder.getAbsolutePath()));
} else if (folder.exists() == false) {
// folder is not there, we create it and return
folder.mkdirs();
@@ -1466,14 +1199,14 @@ public final class AvdManager {
/**
* Parses an AVD .ini file to create an {@link AvdInfo}.
*
- * @param path The path to the AVD .ini file
+ * @param iniPath The path to the AVD .ini file
* @param log the log object to receive action logs. Cannot be null.
* @return A new {@link AvdInfo} with an {@link AvdStatus} indicating whether this AVD is
* valid or not.
*/
- private AvdInfo parseAvdInfo(File path, ISdkLog log) {
+ private AvdInfo parseAvdInfo(File iniPath, ISdkLog log) {
Map<String, String> map = ProjectProperties.parsePropertyFile(
- new FileWrapper(path),
+ new FileWrapper(iniPath),
log);
String avdPath = map.get(AVD_INFO_PATH);
@@ -1501,8 +1234,8 @@ public final class AvdManager {
}
// get name
- String name = path.getName();
- Matcher matcher = INI_NAME_PATTERN.matcher(path.getName());
+ String name = iniPath.getName();
+ Matcher matcher = INI_NAME_PATTERN.matcher(iniPath.getName());
if (matcher.matches()) {
name = matcher.group(1);
}
@@ -1557,6 +1290,7 @@ public final class AvdManager {
AvdInfo info = new AvdInfo(
name,
+ iniPath,
avdPath,
targetHash,
target,
@@ -1792,7 +1526,7 @@ public final class AvdManager {
}
// now write the config file
- File configIniFile = new File(avd.getPath(), CONFIG_INI);
+ File configIniFile = new File(avd.getDataFolderPath(), CONFIG_INI);
writeIniFile(configIniFile, properties);
// finally create a new AvdInfo for this unbroken avd and add it to the list.
@@ -1801,7 +1535,8 @@ public final class AvdManager {
// FIXME: We may want to create this AvdInfo by reparsing the AVD instead. This could detect other errors.
AvdInfo newAvd = new AvdInfo(
avd.getName(),
- avd.getPath(),
+ avd.getIniFile(),
+ avd.getDataFolderPath(),
avd.getTargetHash(),
avd.getTarget(),
avd.getAbiType(),
diff --git a/sdkmanager/libs/sdkuilib/.classpath b/sdkmanager/libs/sdkuilib/.classpath
index 7f1dec3..9080f57 100644
--- a/sdkmanager/libs/sdkuilib/.classpath
+++ b/sdkmanager/libs/sdkuilib/.classpath
@@ -8,6 +8,6 @@
<classpathentry combineaccessrules="false" kind="src" path="/AndroidPrefs"/>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3"/>
<classpathentry combineaccessrules="false" kind="src" path="/common"/>
- <classpathentry kind="var" path="ANDROID_OUT_FRAMEWORK/swtmenubar.jar"/>
+ <classpathentry kind="var" path="ANDROID_OUT_FRAMEWORK/swtmenubar.jar" sourcepath="/ANDROID_SRC/sdk/swtmenubar/src"/>
<classpathentry kind="output" path="bin"/>
</classpath>
diff --git a/sdkmanager/libs/sdkuilib/README b/sdkmanager/libs/sdkuilib/README
index 3d68520..dee4a24 100644
--- a/sdkmanager/libs/sdkuilib/README
+++ b/sdkmanager/libs/sdkuilib/README
@@ -13,7 +13,7 @@ In order to compile the project:
- Create a new user library named ANDROID_SWT
- Add the following 4 JAR files:
- - prebuild/<platform>/swt/swt.jar
+ - prebuilt/<platform>/swt/swt.jar
- prebuilt/common/eclipse/org.eclipse.core.commands_3.*.jar
- prebuilt/common/eclipse/org.eclipse.equinox.common_3.*.jar
- prebuilt/common/eclipse/org.eclipse.jface_3.*.jar
@@ -30,10 +30,16 @@ Define a classpath variable in Eclipse:
- Open Preferences > Java > Build Path > Classpath Variables
- Create a new classpath variable named ANDROID_OUT_FRAMEWORK
- Set its folder value to <Android tree>/out/host/<platform>/framework
+- Create a new classpath variable named ANDROID_SRC
+- Set its folder value to <Android tree>
You might need to clean the SdkUiLib project (Project > Clean...) after
you add the new classpath variable, otherwise previous errors might not
go away automatically.
+The ANDROID_SRC part should be optional. It allows you to have access to
+the SwtMenuBar generic parts from the Java editor.
+
+
--
EOF
diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/AvdManagerPage.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/AvdManagerPage.java
index 7594f16..7c78983 100755
--- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/AvdManagerPage.java
+++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/AvdManagerPage.java
@@ -17,7 +17,6 @@
package com.android.sdkuilib.internal.repository;
import com.android.prefs.AndroidLocation.AndroidLocationException;
-import com.android.sdklib.internal.avd.AvdManager;
import com.android.sdkuilib.internal.widgets.AvdSelector;
import com.android.sdkuilib.internal.widgets.AvdSelector.DisplayMode;
import com.android.sdkuilib.repository.ISdkChangeListener;
@@ -58,7 +57,7 @@ public class AvdManagerPage extends Composite implements ISdkChangeListener {
try {
label.setText(String.format(
"List of existing Android Virtual Devices located at %s",
- AvdManager.getBaseAvdFolder()));
+ mUpdaterData.getAvdManager().getBaseAvdFolder()));
} catch (AndroidLocationException e) {
label.setText(e.getMessage());
}
diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/PackagesPage.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/PackagesPage.java
index 749f927..708c2d6 100755
--- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/PackagesPage.java
+++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/PackagesPage.java
@@ -56,9 +56,10 @@ import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Link;
+import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
@@ -74,6 +75,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.Map.Entry;
/**
* Page that displays both locally installed packages as well as all known
@@ -86,16 +88,46 @@ public class PackagesPage extends Composite
private static final String ICON_CAT_OTHER = "pkgcat_other_16.png"; //$NON-NLS-1$
private static final String ICON_CAT_PLATFORM = "pkgcat_16.png"; //$NON-NLS-1$
private static final String ICON_SORT_BY_SOURCE = "source_icon16.png"; //$NON-NLS-1$
- private static final String ICON_COLUMN_NAME = "platform_pkg_16.png"; //$NON-NLS-1$
+ private static final String ICON_SORT_BY_API = "platform_pkg_16.png"; //$NON-NLS-1$
private static final String ICON_PKG_NEW = "pkg_new_16.png"; //$NON-NLS-1$
private static final String ICON_PKG_UPDATE = "pkg_update_16.png"; //$NON-NLS-1$
private static final String ICON_PKG_INSTALLED = "pkg_installed_16.png"; //$NON-NLS-1$
+ enum MenuAction {
+ RELOAD (SWT.NONE, "Reload"),
+ SHOW_ADDON_SITES (SWT.NONE, "Manage Sources..."),
+ TOGGLE_SHOW_ARCHIVES (SWT.CHECK, "Show Archives"),
+ TOGGLE_SHOW_INSTALLED_PKG (SWT.CHECK, "Show Installed Packages"),
+ TOGGLE_SHOW_OBSOLETE_PKG (SWT.CHECK, "Show Obsolete Packages"),
+ TOGGLE_SHOW_UPDATE_NEW_PKG (SWT.CHECK, "Show Updates/New Packages"),
+ SORT_API_LEVEL (SWT.RADIO, "Sort by API Level"),
+ SORT_SOURCE (SWT.RADIO, "Sort by Source")
+ ;
+
+ private final int mMenuStyle;
+ private final String mMenuTitle;
+
+ MenuAction(int menuStyle, String menuTitle) {
+ mMenuStyle = menuStyle;
+ mMenuTitle = menuTitle;
+ }
+
+ public int getMenuStyle() {
+ return mMenuStyle;
+ }
+
+ public String getMenuTitle() {
+ return mMenuTitle;
+ }
+ };
+
+ private final Map<MenuAction, MenuItem> mMenuActions = new HashMap<MenuAction, MenuItem>();
+
private final List<PkgItem> mPackages = new ArrayList<PkgItem>();
private final List<PkgCategory> mCategories = new ArrayList<PkgCategory>();
private final UpdaterData mUpdaterData;
- private boolean mDisplayArchives = false; // TODO: toggle via a menu item
+ private boolean mDisplayArchives = false;
private Text mTextSdkOsPath;
private Button mCheckSortSource;
@@ -116,7 +148,7 @@ public class PackagesPage extends Composite
private TreeViewerColumn mColumnStatus;
private Color mColorUpdate;
private Font mTreeFontItalic;
- private Button mButtonReload;
+ private TreeColumn mTreeColumnName;
public PackagesPage(Composite parent, UpdaterData updaterData) {
super(parent, SWT.NONE);
@@ -134,7 +166,7 @@ public class PackagesPage extends Composite
}
}
- protected void createContents(Composite parent) {
+ private void createContents(Composite parent) {
GridLayout gridLayout = new GridLayout(2, false);
gridLayout.marginWidth = 0;
gridLayout.marginHeight = 0;
@@ -169,11 +201,12 @@ public class PackagesPage extends Composite
mTree.setHeaderVisible(true);
mTree.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
+ // column name icon is set in sortPackages() depending on the current filter type
+ // (e.g. API level or source)
mColumnName = new TreeViewerColumn(mTreeViewer, SWT.NONE);
- TreeColumn treeColumn1 = mColumnName.getColumn();
- treeColumn1.setImage(getImage(ICON_COLUMN_NAME));
- treeColumn1.setWidth(340);
- treeColumn1.setText("Name");
+ mTreeColumnName = mColumnName.getColumn();
+ mTreeColumnName.setWidth(340);
+ mTreeColumnName.setText("Name");
mColumnApi = new TreeViewerColumn(mTreeViewer, SWT.NONE);
TreeColumn treeColumn2 = mColumnApi.getColumn();
@@ -197,7 +230,7 @@ public class PackagesPage extends Composite
mGroupOptions = new Composite(mGroupPackages, SWT.NONE);
mGroupOptions.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
- GridLayout gl_GroupOptions = new GridLayout(7, false);
+ GridLayout gl_GroupOptions = new GridLayout(6, false);
gl_GroupOptions.marginWidth = 0;
gl_GroupOptions.marginHeight = 0;
mGroupOptions.setLayout(gl_GroupOptions);
@@ -213,7 +246,6 @@ public class PackagesPage extends Composite
sortPackages(true /*updateButtons*/);
}
});
- mCheckFilterNew.setImage(getImage(ICON_PKG_NEW));
mCheckFilterNew.setSelection(true);
mCheckFilterNew.setText("Updates/New");
@@ -225,7 +257,6 @@ public class PackagesPage extends Composite
sortPackages(true /*updateButtons*/);
}
});
- mCheckFilterInstalled.setImage(getImage(ICON_PKG_INSTALLED));
mCheckFilterInstalled.setSelection(true);
mCheckFilterInstalled.setText("Installed");
@@ -240,17 +271,6 @@ public class PackagesPage extends Composite
mCheckFilterObsolete.setSelection(false);
mCheckFilterObsolete.setText("Obsolete");
- mButtonReload = new Button(mGroupOptions, SWT.NONE);
- mButtonReload.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
- mButtonReload.addSelectionListener(new SelectionAdapter() {
- @Override
- public void widgetSelected(SelectionEvent e) {
- onButtonReload();
- }
- });
- mButtonReload.setToolTipText("Reload the package list");
- mButtonReload.setText("Reload");
-
Label placeholder2 = new Label(mGroupOptions, SWT.NONE);
placeholder2.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
@@ -278,7 +298,6 @@ public class PackagesPage extends Composite
expandInitial(mCategories);
}
});
- mCheckSortApi.setImage(getImage(ICON_COLUMN_NAME));
mCheckSortApi.setText("API level");
mCheckSortApi.setSelection(true);
@@ -292,19 +311,8 @@ public class PackagesPage extends Composite
expandInitial(mCategories);
}
});
- mCheckSortSource.setImage(getImage(ICON_SORT_BY_SOURCE));
mCheckSortSource.setText("Source");
- Link link = new Link(mGroupOptions, SWT.NONE);
- link.addSelectionListener(new SelectionAdapter() {
- @Override
- public void widgetSelected(SelectionEvent e) {
- onButtonAddonSites();
- }
- });
- link.setToolTipText("Manage the list of add-on sites");
- link.setText("<a>Manage Sources</a>");
-
new Label(mGroupOptions, SWT.NONE);
new Label(mGroupOptions, SWT.NONE);
@@ -335,6 +343,124 @@ public class PackagesPage extends Composite
// Hide everything down-below from SWT designer
//$hide>>$
+
+ // --- menu interactions ---
+
+ public void registerMenuAction(final MenuAction action, MenuItem item) {
+ item.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ Button button = null;
+
+ switch (action) {
+ case RELOAD:
+ loadPackages();
+ break;
+ case SHOW_ADDON_SITES:
+ AddonSitesDialog d = new AddonSitesDialog(getShell(), mUpdaterData);
+ if (d.open()) {
+ loadPackages();
+ }
+ break;
+ case TOGGLE_SHOW_ARCHIVES:
+ mDisplayArchives = !mDisplayArchives;
+ sortPackages(true /*updateButtons*/);
+ break;
+ case TOGGLE_SHOW_INSTALLED_PKG:
+ button = mCheckFilterInstalled;
+ break;
+ case TOGGLE_SHOW_OBSOLETE_PKG:
+ button = mCheckFilterObsolete;
+ break;
+ case TOGGLE_SHOW_UPDATE_NEW_PKG:
+ button = mCheckFilterNew;
+ break;
+ case SORT_API_LEVEL:
+ button = mCheckSortApi;
+ break;
+ case SORT_SOURCE:
+ button = mCheckSortSource;
+ break;
+ }
+
+ if (button != null && !button.isDisposed()) {
+ // Toggle this button (radio or checkbox)
+
+ boolean value = button.getSelection();
+
+ // SWT doesn't automatically switch radio buttons when using the
+ // Widget#setSelection method, so we'll do it here manually.
+ if (!value && (button.getStyle() & SWT.RADIO) != 0) {
+ // we'll be selecting this radio button, so deselect all ther other ones
+ // in the parent group.
+ for (Control child : button.getParent().getChildren()) {
+ if (child instanceof Button &&
+ child != button &&
+ (child.getStyle() & SWT.RADIO) != 0) {
+ ((Button) child).setSelection(value);
+ }
+ }
+ }
+
+ button.setSelection(!value);
+
+ // SWT doesn't actually invoke the listeners when using Widget#setSelection
+ // so let's run the actual action.
+ button.notifyListeners(SWT.Selection, new Event());
+ }
+
+ updateMenuCheckmarks();
+ }
+ });
+
+ mMenuActions.put(action, item);
+ }
+
+ // --- internal methods ---
+
+ private void updateMenuCheckmarks() {
+
+ for (Entry<MenuAction, MenuItem> entry : mMenuActions.entrySet()) {
+ MenuAction action = entry.getKey();
+ MenuItem item = entry.getValue();
+
+ if (action.getMenuStyle() == SWT.NONE) {
+ continue;
+ }
+
+ boolean value = false;
+ Button button = null;
+
+ switch (action) {
+ case TOGGLE_SHOW_ARCHIVES:
+ value = mDisplayArchives;
+ break;
+ case TOGGLE_SHOW_INSTALLED_PKG:
+ button = mCheckFilterInstalled;
+ break;
+ case TOGGLE_SHOW_OBSOLETE_PKG:
+ button = mCheckFilterObsolete;
+ break;
+ case TOGGLE_SHOW_UPDATE_NEW_PKG:
+ button = mCheckFilterNew;
+ break;
+ case SORT_API_LEVEL:
+ button = mCheckSortApi;
+ break;
+ case SORT_SOURCE:
+ button = mCheckSortSource;
+ break;
+ }
+
+ if (button != null && !button.isDisposed()) {
+ value = button.getSelection();
+ }
+
+ item.setSelection(value);
+ }
+
+ }
+
private void postCreate() {
if (mUpdaterData != null) {
mTextSdkOsPath.setText(mUpdaterData.getOsSdkRoot());
@@ -442,6 +568,7 @@ public class PackagesPage extends Composite
} finally {
enableUi(mGroupPackages, true);
updateButtonsState();
+ updateMenuCheckmarks();
}
}
@@ -458,12 +585,13 @@ public class PackagesPage extends Composite
private void sortPackages(boolean updateButtons) {
if (mCheckSortApi != null && !mCheckSortApi.isDisposed() && mCheckSortApi.getSelection()) {
- sortByAPI();
+ sortByApiLevel();
} else {
sortBySource();
}
if (updateButtons) {
updateButtonsState();
+ updateMenuCheckmarks();
}
}
@@ -472,10 +600,14 @@ public class PackagesPage extends Composite
* This does an update in-place of the mCategories list so that the table
* can preserve its state (checked / expanded / selected) properly.
*/
- private void sortByAPI() {
+ private void sortByApiLevel() {
ImageFactory imgFactory = mUpdaterData.getImageFactory();
+ if (!mTreeColumnName.isDisposed()) {
+ mTreeColumnName.setImage(getImage(ICON_SORT_BY_API));
+ }
+
// keep a map of the initial state so that we can detect which items or categories are
// no longer being used, so that we can removed them at the end of the in-place update.
final Map<Integer, Pair<PkgCategory, HashSet<PkgItem>> > unusedItemsMap =
@@ -612,6 +744,11 @@ public class PackagesPage extends Composite
* Recompute the tree by sorting all packages by source.
*/
private void sortBySource() {
+
+ if (!mTreeColumnName.isDisposed()) {
+ mTreeColumnName.setImage(getImage(ICON_SORT_BY_SOURCE));
+ }
+
mCategories.clear();
Set<SdkSource> sourceSet = new HashSet<SdkSource>();
@@ -816,18 +953,7 @@ public class PackagesPage extends Composite
mButtonDelete.setEnabled(canDelete);
}
- protected void onButtonReload() {
- loadPackages();
- }
-
- protected void onButtonAddonSites() {
- AddonSitesDialog d = new AddonSitesDialog(getShell(), mUpdaterData);
- if (d.open()) {
- loadPackages();
- }
- }
-
- protected void onButtonInstall() {
+ private void onButtonInstall() {
ArrayList<Archive> archives = new ArrayList<Archive>();
if (mDisplayArchives) {
@@ -883,7 +1009,7 @@ public class PackagesPage extends Composite
}
}
- protected void onButtonDelete() {
+ private void onButtonDelete() {
// Find selected local packages to be delete
Object[] checked = mTreeViewer.getCheckedElements();
if (checked == null) {
diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterWindowImpl2.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterWindowImpl2.java
index dfdf886..6b3cd66 100755
--- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterWindowImpl2.java
+++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterWindowImpl2.java
@@ -21,6 +21,7 @@ import com.android.menubar.IMenuBarCallback;
import com.android.menubar.MenuBarEnhancer;
import com.android.sdklib.ISdkLog;
import com.android.sdklib.SdkConstants;
+import com.android.sdkuilib.internal.repository.PackagesPage.MenuAction;
import com.android.sdkuilib.internal.repository.icons.ImageFactory;
import com.android.sdkuilib.internal.tasks.ProgressView;
import com.android.sdkuilib.internal.tasks.ProgressViewFactory;
@@ -100,9 +101,9 @@ public class UpdaterWindowImpl2 implements IUpdaterWindow {
}
createShell();
- createMenuBar();
preCreateContent();
createContents();
+ createMenuBar();
mShell.open();
mShell.layout();
@@ -187,30 +188,58 @@ public class UpdaterWindowImpl2 implements IUpdaterWindow {
Menu menuPkgs = new Menu(menuBarPackages);
menuBarPackages.setMenu(menuPkgs);
- MenuItem ShowUpdatesnew = new MenuItem(menuPkgs, SWT.NONE);
- ShowUpdatesnew.setText("Show Updates/New Packages");
-
- MenuItem ShowInstalled = new MenuItem(menuPkgs, SWT.NONE);
- ShowInstalled.setText("Show Installed Packages");
-
- MenuItem ShowObsoletePackages = new MenuItem(menuPkgs, SWT.NONE);
- ShowObsoletePackages.setText("Show Obsolete Packages");
-
- MenuItem ShowArchives = new MenuItem(menuPkgs, SWT.NONE);
- ShowArchives.setText("Show Archives");
+ MenuItem showUpdatesNew = new MenuItem(menuPkgs,
+ MenuAction.TOGGLE_SHOW_UPDATE_NEW_PKG.getMenuStyle());
+ showUpdatesNew.setText(
+ MenuAction.TOGGLE_SHOW_UPDATE_NEW_PKG.getMenuTitle());
+ mPkgPage.registerMenuAction(
+ MenuAction.TOGGLE_SHOW_UPDATE_NEW_PKG, showUpdatesNew);
+
+ MenuItem showInstalled = new MenuItem(menuPkgs,
+ MenuAction.TOGGLE_SHOW_INSTALLED_PKG.getMenuStyle());
+ showInstalled.setText(
+ MenuAction.TOGGLE_SHOW_INSTALLED_PKG.getMenuTitle());
+ mPkgPage.registerMenuAction(
+ MenuAction.TOGGLE_SHOW_INSTALLED_PKG, showInstalled);
+
+ MenuItem showObsoletePackages = new MenuItem(menuPkgs,
+ MenuAction.TOGGLE_SHOW_OBSOLETE_PKG.getMenuStyle());
+ showObsoletePackages.setText(
+ MenuAction.TOGGLE_SHOW_OBSOLETE_PKG.getMenuTitle());
+ mPkgPage.registerMenuAction(
+ MenuAction.TOGGLE_SHOW_OBSOLETE_PKG, showObsoletePackages);
+
+ MenuItem showArchives = new MenuItem(menuPkgs,
+ MenuAction.TOGGLE_SHOW_ARCHIVES.getMenuStyle());
+ showArchives.setText(
+ MenuAction.TOGGLE_SHOW_ARCHIVES.getMenuTitle());
+ mPkgPage.registerMenuAction(
+ MenuAction.TOGGLE_SHOW_ARCHIVES, showArchives);
new MenuItem(menuPkgs, SWT.SEPARATOR);
- MenuItem sortByApi = new MenuItem(menuPkgs, SWT.NONE);
- sortByApi.setText("Sort by API Level");
+ MenuItem sortByApi = new MenuItem(menuPkgs,
+ MenuAction.SORT_API_LEVEL.getMenuStyle());
+ sortByApi.setText(
+ MenuAction.SORT_API_LEVEL.getMenuTitle());
+ mPkgPage.registerMenuAction(
+ MenuAction.SORT_API_LEVEL, sortByApi);
- MenuItem sortBySource = new MenuItem(menuPkgs, SWT.NONE);
- sortBySource.setText("Sort by Source");
+ MenuItem sortBySource = new MenuItem(menuPkgs,
+ MenuAction.SORT_SOURCE.getMenuStyle());
+ sortBySource.setText(
+ MenuAction.SORT_SOURCE.getMenuTitle());
+ mPkgPage.registerMenuAction(
+ MenuAction.SORT_SOURCE, sortBySource);
new MenuItem(menuPkgs, SWT.SEPARATOR);
- MenuItem reload = new MenuItem(menuPkgs, SWT.NONE);
- reload.setText("Reload");
+ MenuItem reload = new MenuItem(menuPkgs,
+ MenuAction.RELOAD.getMenuStyle());
+ reload.setText(
+ MenuAction.RELOAD.getMenuTitle());
+ mPkgPage.registerMenuAction(
+ MenuAction.RELOAD, reload);
MenuItem menuBarTools = new MenuItem(menuBar, SWT.CASCADE);
menuBarTools.setText("Tools");
@@ -221,8 +250,12 @@ public class UpdaterWindowImpl2 implements IUpdaterWindow {
MenuItem manageAvds = new MenuItem(menuTools, SWT.NONE);
manageAvds.setText("Manage AVDs...");
- MenuItem manageSources = new MenuItem(menuTools, SWT.NONE);
- manageSources.setText("Manage Sources...");
+ MenuItem manageSources = new MenuItem(menuTools,
+ MenuAction.SHOW_ADDON_SITES.getMenuStyle());
+ manageSources.setText(
+ MenuAction.SHOW_ADDON_SITES.getMenuTitle());
+ mPkgPage.registerMenuAction(
+ MenuAction.SHOW_ADDON_SITES, manageSources);
MenuBarEnhancer.setupMenu(APP_NAME, menuTools, new IMenuBarCallback() {
public void onPreferencesMenuSelected() {
@@ -237,7 +270,9 @@ public class UpdaterWindowImpl2 implements IUpdaterWindow {
public void printError(String format, Object... args) {
if (mUpdaterData != null) {
- mUpdaterData.getSdkLog().warning(format, args);
+ // TODO: right now dump to stderr. Use sdklog later.
+ //mUpdaterData.getSdkLog().error(null, format, args);
+ System.err.printf(format, args);
}
}
});
diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdCreationDialog.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdCreationDialog.java
index b545dbd..0932378 100644
--- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdCreationDialog.java
+++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdCreationDialog.java
@@ -22,10 +22,10 @@ import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.ISdkLog;
import com.android.sdklib.SdkConstants;
import com.android.sdklib.SdkManager;
+import com.android.sdklib.internal.avd.AvdInfo;
import com.android.sdklib.internal.avd.AvdManager;
import com.android.sdklib.internal.avd.HardwareProperties;
import com.android.sdklib.internal.avd.AvdManager.AvdConflict;
-import com.android.sdklib.internal.avd.AvdManager.AvdInfo;
import com.android.sdklib.internal.avd.HardwareProperties.HardwareProperty;
import com.android.sdklib.internal.project.ProjectProperties;
import com.android.sdkuilib.internal.repository.icons.ImageFactory;
@@ -1312,7 +1312,7 @@ final class AvdCreationDialog extends GridDialog {
File avdFolder = null;
try {
- avdFolder = AvdManager.AvdInfo.getAvdFolder(avdName);
+ avdFolder = AvdInfo.getDefaultAvdFolder(mAvdManager, avdName);
} catch (AndroidLocationException e) {
return false;
}
diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdDetailsDialog.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdDetailsDialog.java
index 46f3eaf..6a85c14 100644
--- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdDetailsDialog.java
+++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdDetailsDialog.java
@@ -18,9 +18,9 @@ package com.android.sdkuilib.internal.widgets;
import com.android.sdklib.AndroidVersion;
import com.android.sdklib.IAndroidTarget;
+import com.android.sdklib.internal.avd.AvdInfo;
import com.android.sdklib.internal.avd.AvdManager;
-import com.android.sdklib.internal.avd.AvdManager.AvdInfo;
-import com.android.sdklib.internal.avd.AvdManager.AvdInfo.AvdStatus;
+import com.android.sdklib.internal.avd.AvdInfo.AvdStatus;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
@@ -103,7 +103,7 @@ final class AvdDetailsDialog extends Dialog {
displayValue(c, "Name:", mAvdInfo.getName());
displayValue(c, "ABI:", AvdInfo.getPrettyAbiType(mAvdInfo.getAbiType()));
- displayValue(c, "Path:", mAvdInfo.getPath());
+ displayValue(c, "Path:", mAvdInfo.getDataFolderPath());
if (mAvdInfo.getStatus() != AvdStatus.OK) {
displayValue(c, "Error:", mAvdInfo.getErrorMessage());
diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdSelector.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdSelector.java
index 86a094f..56f2c7e 100644
--- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdSelector.java
+++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdSelector.java
@@ -20,9 +20,9 @@ import com.android.prefs.AndroidLocation.AndroidLocationException;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.ISdkLog;
import com.android.sdklib.NullSdkLog;
+import com.android.sdklib.internal.avd.AvdInfo;
import com.android.sdklib.internal.avd.AvdManager;
-import com.android.sdklib.internal.avd.AvdManager.AvdInfo;
-import com.android.sdklib.internal.avd.AvdManager.AvdInfo.AvdStatus;
+import com.android.sdklib.internal.avd.AvdInfo.AvdStatus;
import com.android.sdklib.internal.repository.ITask;
import com.android.sdklib.internal.repository.ITaskMonitor;
import com.android.sdkuilib.internal.repository.SettingsController;
diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdStartDialog.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdStartDialog.java
index 77f47d1..7731dc1 100644
--- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdStartDialog.java
+++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdStartDialog.java
@@ -16,8 +16,8 @@
package com.android.sdkuilib.internal.widgets;
+import com.android.sdklib.internal.avd.AvdInfo;
import com.android.sdklib.internal.avd.AvdManager;
-import com.android.sdklib.internal.avd.AvdManager.AvdInfo;
import com.android.sdkuilib.internal.repository.SettingsController;
import com.android.sdkuilib.ui.GridDialog;
diff --git a/swtmenubar/.classpath b/swtmenubar/.classpath
index 827ba88..0f69dc5 100644
--- a/swtmenubar/.classpath
+++ b/swtmenubar/.classpath
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
- <classpathentry excluding="org/eclipse/ui/internal/cocoa/CocoaUIEnhancer.java" kind="src" path="src"/>
+ <classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/ANDROID_SWT"/>
<classpathentry kind="output" path="bin"/>
diff --git a/swtmenubar/Android.mk b/swtmenubar/Android.mk
index 333684f..25e80da 100644
--- a/swtmenubar/Android.mk
+++ b/swtmenubar/Android.mk
@@ -27,7 +27,10 @@ endif
LOCAL_MODULE := swtmenubar
LOCAL_MODULE_TAGS := optional
-LOCAL_JAVA_LIBRARIES := swt
+LOCAL_JAVA_LIBRARIES := \
+ swt \
+ org.eclipse.jface_3.4.2.M20090107-0800
+
include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/swtmenubar/README b/swtmenubar/README
index cc9fa61..ba7c25a 100755
--- a/swtmenubar/README
+++ b/swtmenubar/README
@@ -57,9 +57,24 @@ Then add a variable to the Build Path of the target project:
- Select swtmenubar.jar (which you previously built at step 1)
-Remember that if you then edit the SwtMenuBar project in Eclipse
-you will need to rebuild it using the command-line before the
-changes are propagated in the target applications that uses it.
+3- Tip for developing this library:
+
+Keep in mind that src-darwin folder must not be added to the
+source folder list, otherwise the library would not compile
+on Windows or Linux.
+
+If you change anything to IMenuBarCallback, make sure to test
+on a Mac to be sure you're not breaking the API.
+
+To work on this on a Mac, you can either:
+a- simply temporarily add src-darwin as a source folder to the
+ build path and remove it before submitting.
+b- or directly edit the java files and rebuild the library using
+ 'make swtmenubar' from a shell.
+
+To test the library, use 'make swtmenubar'. This will build the
+library in out/... and the sdkmanager project is already setup
+to find it there.
--
EOF
diff --git a/swtmenubar/src-darwin/com/android/menubar/internal/MenuBarEnhancerCarbon.java b/swtmenubar/src-darwin/com/android/menubar/internal/MenuBarEnhancerCarbon.java
index 328597a..45dacfb 100755
--- a/swtmenubar/src-darwin/com/android/menubar/internal/MenuBarEnhancerCarbon.java
+++ b/swtmenubar/src-darwin/com/android/menubar/internal/MenuBarEnhancerCarbon.java
@@ -38,11 +38,14 @@ public final class MenuBarEnhancerCarbon implements IMenuBarEnhancer {
public MenuBarEnhancerCarbon() {
}
+ public MenuBarMode getMenuBarMode() {
+ return MenuBarMode.MAC_OS;
+ }
+
public void setupMenu(
String appName,
- Menu swtMenu,
+ Display display,
final IMenuBarCallback callbacks) {
- final Display display = swtMenu.getDisplay();
// Callback target
Object target = new Object() {
diff --git a/swtmenubar/src-darwin/com/android/menubar/internal/MenuBarEnhancerCocoa.java b/swtmenubar/src-darwin/com/android/menubar/internal/MenuBarEnhancerCocoa.java
new file mode 100644
index 0000000..170603a
--- /dev/null
+++ b/swtmenubar/src-darwin/com/android/menubar/internal/MenuBarEnhancerCocoa.java
@@ -0,0 +1,341 @@
+/*
+ * Copyright (C) 2011 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.
+ *
+ * History:
+ * Original code by the <a href="http://www.simidude.com/blog/2008/macify-a-swt-application-in-a-cross-platform-way/">CarbonUIEnhancer from Agynami</a>
+ * with the implementation being modified from the <a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.ui.cocoa/src/org/eclipse/ui/internal/cocoa/CocoaUIEnhancer.java">org.eclipse.ui.internal.cocoa.CocoaUIEnhancer</a>,
+ * then modified by http://www.transparentech.com/opensource/cocoauienhancer to use reflection
+ * rather than 'link' to SWT cocoa, and finally modified to be usable by the SwtMenuBar project.
+ */
+
+package com.android.menubar.internal;
+
+import com.android.menubar.IMenuBarCallback;
+import com.android.menubar.IMenuBarEnhancer;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.internal.C;
+import org.eclipse.swt.internal.Callback;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Menu;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class MenuBarEnhancerCocoa implements IMenuBarEnhancer {
+
+ private static final long kAboutMenuItem = 0;
+ private static final long kPreferencesMenuItem = 2;
+ // private static final long kServicesMenuItem = 4;
+ // private static final long kHideApplicationMenuItem = 6;
+ private static final long kQuitMenuItem = 10;
+
+ static long mSelPreferencesMenuItemSelected;
+ static long mSelAboutMenuItemSelected;
+ static Callback mProc3Args;
+
+ private String mAppName;
+
+ /**
+ * Class invoked via the Callback object to run the about and preferences
+ * actions.
+ * <p>
+ * If you don't use JFace in your application (SWT only), change the
+ * {@link org.eclipse.jface.action.IAction}s to
+ * {@link org.eclipse.swt.widgets.Listener}s.
+ * </p>
+ */
+ private static class ActionProctarget {
+ private final IMenuBarCallback mCallbacks;
+
+ public ActionProctarget(IMenuBarCallback callbacks) {
+ mCallbacks = callbacks;
+ }
+
+ /**
+ * Will be called on 32bit SWT.
+ */
+ @SuppressWarnings("unused")
+ public int actionProc(int id, int sel, int arg0) {
+ return (int) actionProc((long) id, (long) sel, (long) arg0);
+ }
+
+ /**
+ * Will be called on 64bit SWT.
+ */
+ public long actionProc(long id, long sel, long arg0) {
+ if (sel == mSelAboutMenuItemSelected) {
+ mCallbacks.onAboutMenuSelected();
+ } else if (sel == mSelPreferencesMenuItemSelected) {
+ mCallbacks.onPreferencesMenuSelected();
+ } else {
+ // Unknown selection!
+ }
+ // Return value is not used.
+ return 0;
+ }
+ }
+
+ /**
+ * Construct a new CocoaUIEnhancer.
+ *
+ * @param mAppName The name of the application. It will be used to customize
+ * the About and Quit menu items. If you do not wish to customize
+ * the About and Quit menu items, just pass <tt>null</tt> here.
+ */
+ public MenuBarEnhancerCocoa() {
+ }
+
+ public MenuBarMode getMenuBarMode() {
+ return MenuBarMode.MAC_OS;
+ }
+
+ /**
+ * Setup the About and Preferences native menut items with the
+ * given application name and links them to the callback.
+ *
+ * @param appName The application name.
+ * @param display The SWT display. Must not be null.
+ * @param callbacks The callbacks invoked by the menus.
+ */
+ public void setupMenu(
+ String appName,
+ Display display,
+ IMenuBarCallback callbacks) {
+
+ mAppName = appName;
+
+ // This is our callback object whose 'actionProc' method will be called
+ // when the About or Preferences menuItem is invoked.
+ ActionProctarget target = new ActionProctarget(callbacks);
+
+ try {
+ // Initialize the menuItems.
+ initialize(target);
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+
+ // Schedule disposal of callback object
+ display.disposeExec(new Runnable() {
+ public void run() {
+ invoke(mProc3Args, "dispose");
+ }
+ });
+ }
+
+ private void initialize(Object callbackObject)
+ throws Exception {
+
+ Class<?> osCls = classForName("org.eclipse.swt.internal.cocoa.OS");
+
+ // Register names in objective-c.
+ if (mSelAboutMenuItemSelected == 0) {
+ mSelPreferencesMenuItemSelected = registerName(osCls, "preferencesMenuItemSelected:"); //$NON-NLS-1$
+ mSelAboutMenuItemSelected = registerName(osCls, "aboutMenuItemSelected:"); //$NON-NLS-1$
+ }
+
+ // Create an SWT Callback object that will invoke the actionProc method
+ // of our internal callback Object.
+ mProc3Args = new Callback(callbackObject, "actionProc", 3); //$NON-NLS-1$
+ Method getAddress = Callback.class.getMethod("getAddress", new Class[0]);
+ Object object = getAddress.invoke(mProc3Args, (Object[]) null);
+ long proc3 = convertToLong(object);
+ if (proc3 == 0) {
+ SWT.error(SWT.ERROR_NO_MORE_CALLBACKS);
+ }
+
+ Class<?> nsMenuCls = classForName("org.eclipse.swt.internal.cocoa.NSMenu");
+ Class<?> nsMenuitemCls = classForName("org.eclipse.swt.internal.cocoa.NSMenuItem");
+ Class<?> nsStringCls = classForName("org.eclipse.swt.internal.cocoa.NSString");
+ Class<?> nsApplicationCls = classForName("org.eclipse.swt.internal.cocoa.NSApplication");
+
+ // Instead of creating a new delegate class in objective-c,
+ // just use the current SWTApplicationDelegate. An instance of this
+ // is a field of the Cocoa Display object and is already the target
+ // for the menuItems. So just get this class and add the new methods
+ // to it.
+ object = invoke(osCls, "objc_lookUpClass", new Object[] {
+ "SWTApplicationDelegate"
+ });
+ long cls = convertToLong(object);
+
+ // Add the action callbacks for Preferences and About menu items.
+ invoke(osCls, "class_addMethod",
+ new Object[] {
+ wrapPointer(cls),
+ wrapPointer(mSelPreferencesMenuItemSelected),
+ wrapPointer(proc3), "@:@"}); //$NON-NLS-1$
+ invoke(osCls, "class_addMethod",
+ new Object[] {
+ wrapPointer(cls),
+ wrapPointer(mSelAboutMenuItemSelected),
+ wrapPointer(proc3), "@:@"}); //$NON-NLS-1$
+
+ // Get the Mac OS X Application menu.
+ Object sharedApplication = invoke(nsApplicationCls, "sharedApplication");
+ Object mainMenu = invoke(sharedApplication, "mainMenu");
+ Object mainMenuItem = invoke(nsMenuCls, mainMenu, "itemAtIndex", new Object[] {
+ wrapPointer(0)
+ });
+ Object appMenu = invoke(mainMenuItem, "submenu");
+
+ // Create the About <application-name> menu command
+ Object aboutMenuItem =
+ invoke(nsMenuCls, appMenu, "itemAtIndex", new Object[] {
+ wrapPointer(kAboutMenuItem)
+ });
+ if (mAppName != null) {
+ Object nsStr = invoke(nsStringCls, "stringWith", new Object[] {
+ "About " + mAppName
+ });
+ invoke(nsMenuitemCls, aboutMenuItem, "setTitle", new Object[] {
+ nsStr
+ });
+ }
+ // Rename the quit action.
+ if (mAppName != null) {
+ Object quitMenuItem =
+ invoke(nsMenuCls, appMenu, "itemAtIndex", new Object[] {
+ wrapPointer(kQuitMenuItem)
+ });
+ Object nsStr = invoke(nsStringCls, "stringWith", new Object[] {
+ "Quit " + mAppName
+ });
+ invoke(nsMenuitemCls, quitMenuItem, "setTitle", new Object[] {
+ nsStr
+ });
+ }
+
+ // Enable the Preferences menuItem.
+ Object prefMenuItem =
+ invoke(nsMenuCls, appMenu, "itemAtIndex", new Object[] {
+ wrapPointer(kPreferencesMenuItem)
+ });
+ invoke(nsMenuitemCls, prefMenuItem, "setEnabled", new Object[] {
+ true
+ });
+
+ // Set the action to execute when the About or Preferences menuItem is
+ // invoked.
+ //
+ // We don't need to set the target here as the current target is the
+ // SWTApplicationDelegate and we have registerd the new selectors on
+ // it. So just set the new action to invoke the selector.
+ invoke(nsMenuitemCls, prefMenuItem, "setAction",
+ new Object[] {
+ wrapPointer(mSelPreferencesMenuItemSelected)
+ });
+ invoke(nsMenuitemCls, aboutMenuItem, "setAction",
+ new Object[] {
+ wrapPointer(mSelAboutMenuItemSelected)
+ });
+ }
+
+ private long registerName(Class<?> osCls, String name)
+ throws IllegalArgumentException, SecurityException, IllegalAccessException,
+ InvocationTargetException, NoSuchMethodException {
+ Object object = invoke(osCls, "sel_registerName", new Object[] {
+ name
+ });
+ return convertToLong(object);
+ }
+
+ private long convertToLong(Object object) {
+ if (object instanceof Integer) {
+ Integer i = (Integer) object;
+ return i.longValue();
+ }
+ if (object instanceof Long) {
+ Long l = (Long) object;
+ return l.longValue();
+ }
+ return 0;
+ }
+
+ private static Object wrapPointer(long value) {
+ Class<?> PTR_CLASS = C.PTR_SIZEOF == 8 ? long.class : int.class;
+ if (PTR_CLASS == long.class) {
+ return new Long(value);
+ } else {
+ return new Integer((int) value);
+ }
+ }
+
+ private static Object invoke(Class<?> clazz, String methodName, Object[] args) {
+ return invoke(clazz, null, methodName, args);
+ }
+
+ private static Object invoke(Class<?> clazz, Object target, String methodName, Object[] args) {
+ try {
+ Class<?>[] signature = new Class<?>[args.length];
+ for (int i = 0; i < args.length; i++) {
+ Class<?> thisClass = args[i].getClass();
+ if (thisClass == Integer.class)
+ signature[i] = int.class;
+ else if (thisClass == Long.class)
+ signature[i] = long.class;
+ else if (thisClass == Byte.class)
+ signature[i] = byte.class;
+ else if (thisClass == Boolean.class)
+ signature[i] = boolean.class;
+ else
+ signature[i] = thisClass;
+ }
+ Method method = clazz.getMethod(methodName, signature);
+ return method.invoke(target, args);
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ private Class<?> classForName(String classname) {
+ try {
+ Class<?> cls = Class.forName(classname);
+ return cls;
+ } catch (ClassNotFoundException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ private Object invoke(Class<?> cls, String methodName) {
+ return invoke(cls, methodName, (Class<?>[]) null, (Object[]) null);
+ }
+
+ private Object invoke(Class<?> cls, String methodName, Class<?>[] paramTypes,
+ Object... arguments) {
+ try {
+ Method m = cls.getDeclaredMethod(methodName, paramTypes);
+ return m.invoke(null, arguments);
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ private Object invoke(Object obj, String methodName) {
+ return invoke(obj, methodName, (Class<?>[]) null, (Object[]) null);
+ }
+
+ private Object invoke(Object obj, String methodName, Class<?>[] paramTypes, Object... arguments) {
+ try {
+ Method m = obj.getClass().getDeclaredMethod(methodName, paramTypes);
+ return m.invoke(obj, arguments);
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+}
diff --git a/swtmenubar/src-darwin/com/android/menubar/internal/MenuBarEnhancerCocoa.java.txt b/swtmenubar/src-darwin/com/android/menubar/internal/MenuBarEnhancerCocoa.java.txt
deleted file mode 100755
index 591f253..0000000
--- a/swtmenubar/src-darwin/com/android/menubar/internal/MenuBarEnhancerCocoa.java.txt
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * Copyright (C) 2011 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.menubar.internal;
-
-import com.android.menubar.IMenuBarCallback;
-import com.android.menubar.IMenuBarEnhancer;
-import com.android.menubar.MenuBarEnhancer;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.internal.C;
-import org.eclipse.swt.internal.Callback;
-import org.eclipse.swt.internal.cocoa.NSApplication;
-import org.eclipse.swt.internal.cocoa.NSMenu;
-import org.eclipse.swt.internal.cocoa.NSMenuItem;
-import org.eclipse.swt.internal.cocoa.NSObject;
-import org.eclipse.swt.internal.cocoa.OS;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Menu;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-
-/**
- * Implementation of IMenuBarEnhancer for MacOS Cocoa SWT
- * <p/>
- * Note: this is currently deactivated since we are not currently
- * shipping a version of SWT.jar that has cocoa support (only carbon).
- */
-public final class MenuBarEnhancerCocoa implements IMenuBarEnhancer {
-
- private static final int kAboutMenuItem = 0;
- private static final int kPreferencesMenuItem = 2;
- private static final int kServicesMenuItem = 4;
- private static final int kHideApplicationMenuItem = 6;
- private static final int kQuitMenuItem = 10;
-
- private EnhancerDelegate mDelegate;
- private long mDelegateJniRef;
- private IMenuBarCallback mCallbacks;
-
- public static class EnhancerDelegate extends NSObject {
- public EnhancerDelegate() {
- super();
- }
- public EnhancerDelegate(int id) {
- super(id);
- }
-
- }
- static long sel_preferencesMenuItemSelected_;
- static long sel_aboutMenuItemSelected_;
-
- /* This callback is not freed */
- static Callback proc3Args;
- static final byte[] SWT_OBJECT = { 'S', 'W', 'T', '_', 'O', 'B', 'J', 'E', 'C', 'T', '\0' };
-
- public MenuBarEnhancerCocoa() {
- }
-
- public void setupMenu(
- String appName,
- Menu swtMenu,
- IMenuBarCallback callbacks) {
- mCallbacks = callbacks;
- final Display display = swtMenu.getDisplay();
-
- init1();
-
- try {
- mDelegate = new EnhancerDelegate();
- mDelegate.alloc().init();
- //call OS.NewGlobalRef
- Method method = OS.class.getMethod("NewGlobalRef", new Class[] { Object.class });
- Object object = method.invoke(OS.class, new Object[] { this });
- mDelegateJniRef = convertToLong(object);
- } catch (Exception e) {
- // theoretically, one of SecurityException, Illegal*Exception,
- // InvocationTargetException, NoSuch*Exception
- // not expected to happen at all.
- log(e);
- }
-
- if (mDelegateJniRef == 0) {
- SWT.error(SWT.ERROR_NO_HANDLES);
- }
-
- try {
- Field idField = EnhancerDelegate.class.getField("id");
- Object idValue = idField.get(mDelegate);
- invokeMethod(OS.class, "object_setInstanceVariable",
- new Object[] { idValue, SWT_OBJECT, wrapPointer(mDelegateJniRef) });
-
- hookApplicationMenu(appName);
-
- // schedule disposal of callback object
- display.disposeExec(new Runnable() {
- public void run() {
- if (mDelegateJniRef != 0) {
- try {
- invokeMethod(OS.class, "DeleteGlobalRef", new Object[] { wrapPointer(mDelegateJniRef) });
- } catch (Exception e) {
- // theoretically, one of SecurityException,Illegal*Exception,InvocationTargetException,NoSuch*Exception
- // not expected to happen at all.
- log(e);
- }
- }
- mDelegateJniRef = 0;
-
- if (mDelegate != null) {
- mDelegate.release();
- mDelegate = null;
- }
- }
- });
- } catch (Exception e) {
- // theoretically, one of SecurityException,Illegal*Exception,InvocationTargetException,NoSuch*Exception
- // not expected to happen at all.
- log(e);
- }
- }
-
- private long registerName(String name) throws IllegalArgumentException, SecurityException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
- Class clazz = OS.class;
- Object object = invokeMethod(clazz, "sel_registerName", new Object[] {name});
- return convertToLong(object);
- }
-
- private void init1() {
- try {
- if (sel_aboutMenuItemSelected_ == 0) {
- sel_preferencesMenuItemSelected_ = registerName("preferencesMenuItemSelected:"); //$NON-NLS-1$
- sel_aboutMenuItemSelected_ = registerName("aboutMenuItemSelected:"); //$NON-NLS-1$
- init2();
- }
- } catch (Exception e) {
- // theoretically, one of SecurityException,Illegal*Exception,InvocationTargetException,NoSuch*Exception
- // not expected to happen at all.
- log(e);
- }
- }
-
- private void init2() throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, NoSuchFieldException {
- // TODO: These should either move out of Display or be accessible to this class.
- byte[] types = {'*','\0'};
- int size = C.PTR_SIZEOF, align = C.PTR_SIZEOF == 4 ? 2 : 3;
-
- Class clazz = this.getClass();
-
- proc3Args = new Callback(clazz, "actionProc", 3); //$NON-NLS-1$
- //call getAddress
- Method getAddress = Callback.class.getMethod("getAddress", new Class[0]); //$NON-NLS-1$
- Object object = getAddress.invoke(proc3Args, null);
- long proc3 = convertToLong(object);
- if (proc3 == 0) {
- SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);
- }
-
- //call objc_allocateClassPair
- Field field = OS.class.getField("class_NSObject"); //$NON-NLS-1$
- Object fieldObj = field.get(OS.class);
- object = invokeMethod(OS.class, "objc_allocateClassPair", //$NON-NLS-1$
- new Object[] { fieldObj, "SWTCocoaEnhancerDelegate", wrapPointer(0) }); //$NON-NLS-1$
- long cls = convertToLong(object);
-
- invokeMethod(OS.class, "class_addIvar", new Object[] { //$NON-NLS-1$
- wrapPointer(cls), SWT_OBJECT, wrapPointer(size),
- new Byte((byte) align), types });
-
- // Add the action callback
- invokeMethod(OS.class, "class_addMethod", new Object[] { //$NON-NLS-1$
- wrapPointer(cls),
- wrapPointer(sel_preferencesMenuItemSelected_),
- wrapPointer(proc3), "@:@" }); //$NON-NLS-1$
- invokeMethod(OS.class, "class_addMethod", new Object[] { //$NON-NLS-1$
- wrapPointer(cls),
- wrapPointer(sel_aboutMenuItemSelected_),
- wrapPointer(proc3), "@:@" }); //$NON-NLS-1$
-
- invokeMethod(OS.class, "objc_registerClassPair", //$NON-NLS-1$
- new Object[] { wrapPointer(cls) });
- }
-
- private void log(Exception e) {
- mCallbacks.printError("%1$s: %2$s", getClass().getSimpleName(), e.toString()); //$NON-NLS-1$
- }
-
- private void hookApplicationMenu(String appName) {
- try {
- // create About Eclipse menu command
- NSMenu mainMenu = NSApplication.sharedApplication().mainMenu();
- NSMenuItem mainMenuItem = (NSMenuItem) invokeMethod(NSMenu.class, mainMenu,
- "itemAtIndex", new Object[] {wrapPointer(0)}); //$NON-NLS-1$
- NSMenu appMenu = mainMenuItem.submenu();
-
- // add the about action
- NSMenuItem aboutMenuItem = (NSMenuItem) invokeMethod(NSMenu.class, appMenu,
- "itemAtIndex", new Object[] {wrapPointer(kAboutMenuItem)});
- aboutMenuItem.setTitle(NSString.stringWith("About " + appName)); //$NON-NLS-1$
-
- // enable pref menu
- NSMenuItem prefMenuItem = (NSMenuItem) invokeMethod(NSMenu.class, appMenu,
- "itemAtIndex", new Object[] {wrapPointer(kPreferencesMenuItem)}); //$NON-NLS-1$
- prefMenuItem.setEnabled(true);
-
- // disable services menu
- NSMenuItem servicesMenuItem = (NSMenuItem) invokeMethod(NSMenu.class, appMenu,
- "itemAtIndex", new Object[] {wrapPointer(kServicesMenuItem)}); //$NON-NLS-1$
- servicesMenuItem.setEnabled(false);
-
- // Register as a target on the prefs and quit items.
- prefMenuItem.setTarget(mDelegate);
- invokeMethod(NSMenuItem.class, prefMenuItem,
- "setAction", new Object[] {wrapPointer(sel_preferencesMenuItemSelected_)}); //$NON-NLS-1$
- aboutMenuItem.setTarget(mDelegate);
- invokeMethod(NSMenuItem.class, aboutMenuItem,
- "setAction", new Object[] {wrapPointer(sel_aboutMenuItemSelected_)}); //$NON-NLS-1$
- } catch (Exception e) {
- // theoretically, one of SecurityException,Illegal*Exception,InvocationTargetException,NoSuch*Exception
- // not expected to happen at all.
- log(e);
- }
- }
-
- void preferencesMenuItemSelected() {
- try {
- NSMenu mainMenu = NSApplication.sharedApplication().mainMenu();
- NSMenuItem mainMenuItem = (NSMenuItem) invokeMethod(NSMenu.class, mainMenu,
- "itemAtIndex", new Object[] {wrapPointer(0)}); //$NON-NLS-1$
- NSMenu appMenu = mainMenuItem.submenu();
- NSMenuItem prefMenuItem = (NSMenuItem) invokeMethod(NSMenu.class, appMenu, "" + //$NON-NLS-1$
- "itemAtIndex", new Object[] {wrapPointer(kPreferencesMenuItem)}); //$NON-NLS-1$
- try {
- prefMenuItem.setEnabled(false);
-
- mCallbacks.onPreferencesMenuSelected();
- }
- finally {
- prefMenuItem.setEnabled(true);
- }
- } catch (Exception e) {
- // theoretically, one of SecurityException,Illegal*Exception,InvocationTargetException,NoSuch*Exception
- // not expected to happen at all.
- log(e);
- }
- }
-
- void aboutMenuItemSelected() {
- try {
- NSMenu mainMenu = NSApplication.sharedApplication().mainMenu();
- NSMenuItem mainMenuItem = (NSMenuItem) invokeMethod(NSMenu.class, mainMenu,
- "itemAtIndex", new Object[] {wrapPointer(0)}); //$NON-NLS-1$
- NSMenu appMenu = mainMenuItem.submenu();
- NSMenuItem aboutMenuItem = (NSMenuItem) invokeMethod(NSMenu.class, appMenu,
- "itemAtIndex", new Object[] {wrapPointer(kAboutMenuItem)}); //$NON-NLS-1$
- try {
- aboutMenuItem.setEnabled(false);
-
- mCallbacks.onAboutMenuSelected();
- }
- finally {
- aboutMenuItem.setEnabled(true);
- }
- } catch (Exception e) {
- // theoretically, one of SecurityException,Illegal*Exception,InvocationTargetException,NoSuch*Exception
- // not expected to happen at all.
- log(e);
- }
- }
-
- private long convertToLong(Object object) {
- if (object instanceof Integer) {
- Integer i = (Integer) object;
- return i.longValue();
- }
- if (object instanceof Long) {
- Long l = (Long) object;
- return l.longValue();
- }
- return 0;
- }
-
- private static Object invokeMethod(Class clazz, String methodName,
- Object[] args) throws IllegalArgumentException,
- IllegalAccessException, InvocationTargetException,
- SecurityException, NoSuchMethodException {
- return invokeMethod(clazz, null, methodName, args);
- }
-
- private static Object invokeMethod(Class clazz, Object target,
- String methodName, Object[] args) throws IllegalArgumentException,
- IllegalAccessException, InvocationTargetException,
- SecurityException, NoSuchMethodException {
- Class[] signature = new Class[args.length];
- for (int i = 0; i < args.length; i++) {
- Class thisClass = args[i].getClass();
- if (thisClass == Integer.class) {
- signature[i] = int.class;
- } else if (thisClass == Long.class) {
- signature[i] = long.class;
- } else if (thisClass == Byte.class) {
- signature[i] = byte.class;
- } else {
- signature[i] = thisClass;
- }
- }
- Method method = clazz.getMethod(methodName, signature);
- return method.invoke(target, args);
- }
-
- private static Object wrapPointer(long value) {
- Class PTR_CLASS = C.PTR_SIZEOF == 8 ? long.class : int.class;
- if (PTR_CLASS == long.class) {
- return new Long(value);
- } else {
- return new Integer((int)value);
- }
- }
-}
diff --git a/swtmenubar/src/com/android/menubar/IMenuBarEnhancer.java b/swtmenubar/src/com/android/menubar/IMenuBarEnhancer.java
index 1d587e9..d835bd6 100644
--- a/swtmenubar/src/com/android/menubar/IMenuBarEnhancer.java
+++ b/swtmenubar/src/com/android/menubar/IMenuBarEnhancer.java
@@ -16,6 +16,7 @@
package com.android.menubar;
+import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
@@ -25,6 +26,33 @@ import org.eclipse.swt.widgets.Menu;
*/
public interface IMenuBarEnhancer {
+ /** Values that indicate how the menu bar is being handlded. */
+ public enum MenuBarMode {
+ /**
+ * The Mac-specific About and Preferences are being used.
+ * No File > Exit menu should be provided by the application.
+ */
+ MAC_OS,
+ /**
+ * The provided SWT {@link Menu} is being used for About and Options.
+ * The application should provide a File > Exit menu.
+ */
+ GENERIC
+ }
+
+ /**
+ * Returns a {@link MenuBarMode} enum that indicates how the menu bar is going to
+ * or has been modified. This is implementation specific and can be called before or
+ * after {@link #setupMenu}.
+ * <p/>
+ * Callers would typically call that to know if they need to hide or display
+ * menu items. For example when {@link MenuBarMode#MAC_OS} is used, an app
+ * would typically not need to provide any "File > Exit" menu item.
+ *
+ * @return One of the {@link MenuBarMode} values.
+ */
+ public MenuBarMode getMenuBarMode();
+
/**
* Updates the menu bar to provide an About menu item and a Preferences menu item.
* Depending on the platform, the menu items might be decorated with the
@@ -34,13 +62,12 @@ public interface IMenuBarEnhancer {
* {@link MenuBarEnhancer#setupMenu} should be used instead.
*
* @param appName Name used for the About menu item and similar. Must not be null.
- * @param swtMenu For non-mac platform this is the menu where the "About" and
- * the "Preferences" menu items are created. Must not be null.
+ * @param display The SWT display. Must not be null.
* @param callbacks Callbacks called when "About" and "Preferences" menu items are invoked.
* Must not be null.
*/
public void setupMenu(
String appName,
- Menu swtMenu,
+ Display display,
IMenuBarCallback callbacks);
}
diff --git a/swtmenubar/src/com/android/menubar/MenuBarEnhancer.java b/swtmenubar/src/com/android/menubar/MenuBarEnhancer.java
index e40fbe0..eb3e817 100644
--- a/swtmenubar/src/com/android/menubar/MenuBarEnhancer.java
+++ b/swtmenubar/src/com/android/menubar/MenuBarEnhancer.java
@@ -16,9 +16,13 @@
package com.android.menubar;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.Separator;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
@@ -57,49 +61,33 @@ public final class MenuBarEnhancer {
*/
public static IMenuBarEnhancer setupMenu(
String appName,
- Menu swtMenu,
+ final Menu swtMenu,
IMenuBarCallback callbacks) {
- IMenuBarEnhancer enhancer = null;
- String p = SWT.getPlatform();
- String className = null;
- if ("carbon".equals(p)) { //$NON-NLS-1$
- className = "com.android.menubar.internal.MenuBarEnhancerCarbon"; //$NON-NLS-1$
- } else if ("cocoa".equals(p)) { //$NON-NLS-1$
- // Note: we have a Cocoa implementation that is currently disabled
- // since the SWT.jar that we use only contain Carbon implementations.
- //
- // className = "com.android.menubar.internal.MenuBarEnhancerCocoa"; //$NON-NLS-1$
- }
-
- if (className != null) {
- try {
- Class<?> clazz = p.getClass().forName(className);
- enhancer = (IMenuBarEnhancer) clazz.newInstance();
- } catch (Exception e) {
- // Log an error and fallback on the default implementation.
- callbacks.printError(
- "Failed to instantiate %1$s: %2$s", //$NON-NLS-1$
- className,
- e.toString());
- }
- }
+ IMenuBarEnhancer enhancer = getEnhancer(callbacks);
- // Default implementation for other platforms
+ // Default implementation for generic platforms
if (enhancer == null) {
enhancer = new IMenuBarEnhancer() {
+
+ public MenuBarMode getMenuBarMode() {
+ return MenuBarMode.GENERIC;
+ }
+
public void setupMenu(
String appName,
- Menu menu,
+ Display display,
final IMenuBarCallback callbacks) {
- new MenuItem(menu, SWT.SEPARATOR);
+ if (swtMenu.getItemCount() > 0) {
+ new MenuItem(swtMenu, SWT.SEPARATOR);
+ }
// Note: we use "Preferences" on Mac and "Options" on Windows/Linux.
- final MenuItem pref = new MenuItem(menu, SWT.NONE);
- pref.setText("Options...");
+ final MenuItem pref = new MenuItem(swtMenu, SWT.NONE);
+ pref.setText("&Options...");
- final MenuItem about = new MenuItem(menu, SWT.NONE);
- about.setText("About...");
+ final MenuItem about = new MenuItem(swtMenu, SWT.NONE);
+ about.setText("&About...");
pref.addSelectionListener(new SelectionAdapter() {
@Override
@@ -130,8 +118,101 @@ public final class MenuBarEnhancer {
};
}
- enhancer.setupMenu(appName, swtMenu, callbacks);
+ enhancer.setupMenu(appName, swtMenu.getDisplay(), callbacks);
+ return enhancer;
+ }
+
+
+ public static IMenuBarEnhancer setupMenuManager(
+ String appName,
+ Display display,
+ final IMenuManager menuManager,
+ final IAction aboutAction,
+ final IAction preferencesAction,
+ final IAction quitAction) {
+
+ IMenuBarCallback callbacks = new IMenuBarCallback() {
+ public void printError(String format, Object... args) {
+ System.err.println(String.format(format, args));
+ }
+
+ public void onPreferencesMenuSelected() {
+ if (preferencesAction != null) {
+ preferencesAction.run();
+ }
+ }
+
+ public void onAboutMenuSelected() {
+ if (aboutAction != null) {
+ aboutAction.run();
+ }
+ }
+ };
+
+ IMenuBarEnhancer enhancer = getEnhancer(callbacks);
+
+ // Default implementation for generic platforms
+ if (enhancer == null) {
+ enhancer = new IMenuBarEnhancer() {
+
+ public MenuBarMode getMenuBarMode() {
+ return MenuBarMode.GENERIC;
+ }
+
+ public void setupMenu(
+ String appName,
+ Display display,
+ final IMenuBarCallback callbacks) {
+ if (!menuManager.isEmpty()) {
+ menuManager.add(new Separator());
+ }
+
+ if (aboutAction != null) {
+ menuManager.add(aboutAction);
+ }
+ if (preferencesAction != null) {
+ menuManager.add(preferencesAction);
+ }
+ if (quitAction != null) {
+ if (aboutAction != null || preferencesAction != null) {
+ menuManager.add(new Separator());
+ }
+ menuManager.add(quitAction);
+ }
+ }
+ };
+ }
+
+ enhancer.setupMenu(appName, display, callbacks);
return enhancer;
}
+ private static IMenuBarEnhancer getEnhancer(IMenuBarCallback callbacks) {
+ IMenuBarEnhancer enhancer = null;
+ String p = SWT.getPlatform();
+ String className = null;
+ if ("carbon".equals(p)) { //$NON-NLS-1$
+ className = "com.android.menubar.internal.MenuBarEnhancerCarbon"; //$NON-NLS-1$
+ } else if ("cocoa".equals(p)) { //$NON-NLS-1$
+ className = "com.android.menubar.internal.MenuBarEnhancerCocoa"; //$NON-NLS-1$
+ }
+
+ if (System.getenv("DEBUG_SWTMENUBAR") != null) {
+ callbacks.printError("DEBUG SwtMenuBar: SWT=%1$s, class=%2$s", p, className);
+ }
+
+ if (className != null) {
+ try {
+ Class<?> clazz = Class.forName(className);
+ enhancer = (IMenuBarEnhancer) clazz.newInstance();
+ } catch (Exception e) {
+ // Log an error and fallback on the default implementation.
+ callbacks.printError(
+ "Failed to instantiate %1$s: %2$s", //$NON-NLS-1$
+ className,
+ e.toString());
+ }
+ }
+ return enhancer;
+ }
}