diff options
34 files changed, 646 insertions, 378 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/.classpath b/eclipse/plugins/com.android.ide.eclipse.adt/.classpath index 2f2f6a9..e04a925 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/.classpath +++ b/eclipse/plugins/com.android.ide.eclipse.adt/.classpath @@ -7,7 +7,7 @@ <classpathentry kind="lib" path="libs/commons-compress-1.0.jar"/> <classpathentry kind="lib" path="libs/kxml2-2.3.0.jar"/> <classpathentry kind="lib" path="libs/layoutlib_api.jar"/> - <classpathentry kind="lib" path="libs/layoutlib_utils.jar"/> + <classpathentry kind="lib" path="libs/layoutlib_utils.jar" sourcepath="/layoutlib_utils"/> <classpathentry kind="lib" path="libs/ninepatch.jar"/> <classpathentry kind="lib" path="libs/sdklib.jar" sourcepath="/SdkLib"/> <classpathentry kind="lib" path="libs/sdkstats.jar" sourcepath="/SdkStatsService"/> diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF b/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF index 6145db2..0ce3d3d 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF +++ b/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF @@ -46,12 +46,16 @@ Require-Bundle: com.android.ide.eclipse.ddms, org.eclipse.ltk.ui.refactoring, org.eclipse.core.expressions Eclipse-LazyStart: true -Export-Package: com.android.ide.eclipse.adt;x-friends:="com.android.ide.eclipse.tests", - com.android.ide.common.api;x-friends:="com.android.ide.eclipse.tests", +Export-Package: com.android.ide.common.api;x-friends:="com.android.ide.eclipse.tests", com.android.ide.common.layout;x-friends:="com.android.ide.eclipse.tests", + com.android.ide.common.layoutlib;x-friends:="com.android.ide.eclipse.tests", + com.android.ide.common.log;x-friends:="com.android.ide.eclipse.tests", + com.android.ide.common.sdk;x-friends:="com.android.ide.eclipse.tests", + com.android.ide.eclipse.adt;x-friends:="com.android.ide.eclipse.tests", com.android.ide.eclipse.adt.internal;x-friends:="com.android.ide.eclipse.tests", com.android.ide.eclipse.adt.internal.actions;x-friends:="com.android.ide.eclipse.tests", com.android.ide.eclipse.adt.internal.build;x-friends:="com.android.ide.eclipse.tests", + com.android.ide.eclipse.adt.internal.build.builders;x-friends:="com.android.ide.eclipse.tests", com.android.ide.eclipse.adt.internal.editors;x-friends:="com.android.ide.eclipse.tests", com.android.ide.eclipse.adt.internal.editors.descriptors;x-friends:="com.android.ide.eclipse.tests", com.android.ide.eclipse.adt.internal.editors.export;x-friends:="com.android.ide.eclipse.tests", @@ -86,6 +90,7 @@ Export-Package: com.android.ide.eclipse.adt;x-friends:="com.android.ide.eclipse. com.android.ide.eclipse.adt.internal.resources.configurations;x-friends:="com.android.ide.eclipse.tests", com.android.ide.eclipse.adt.internal.resources.manager;x-friends:="com.android.ide.eclipse.tests", com.android.ide.eclipse.adt.internal.sdk;x-friends:="com.android.ide.eclipse.tests", + com.android.ide.eclipse.adt.internal.sourcelookup;x-friends:="com.android.ide.eclipse.tests", com.android.ide.eclipse.adt.internal.ui;x-friends:="com.android.ide.eclipse.tests", com.android.ide.eclipse.adt.internal.wizards.actions;x-friends:="com.android.ide.eclipse.tests", com.android.ide.eclipse.adt.internal.wizards.export;x-friends:="com.android.ide.eclipse.tests", @@ -93,10 +98,10 @@ Export-Package: com.android.ide.eclipse.adt;x-friends:="com.android.ide.eclipse. com.android.ide.eclipse.adt.internal.wizards.newxmlfile;x-friends:="com.android.ide.eclipse.tests", com.android.ide.eclipse.adt.io;x-friends:="com.android.ide.eclipse.tests", com.android.layoutlib.api;x-friends:="com.android.ide.eclipse.tests", - com.android.layoutlib.utils;x-friends:="com.android.ide.eclipse.tests", com.android.ninepatch;x-friends:="com.android.ide.eclipse.tests", com.android.prefs;x-friends:="com.android.ide.eclipse.tests", com.android.sdklib;x-friends:="com.android.ide.eclipse.tests", + com.android.sdklib.annotations;x-friends:="com.android.ide.eclipse.tests", com.android.sdklib.build;x-friends:="com.android.ide.eclipse.tests", com.android.sdklib.internal.avd;x-friends:="com.android.ide.eclipse.tests", com.android.sdklib.internal.build;x-friends:="com.android.ide.eclipse.tests", @@ -106,6 +111,7 @@ Export-Package: com.android.ide.eclipse.adt;x-friends:="com.android.ide.eclipse. com.android.sdklib.io;x-friends:="com.android.ide.eclipse.tests", com.android.sdklib.repository;x-friends:="com.android.ide.eclipse.tests", com.android.sdklib.resources;x-friends:="com.android.ide.eclipse.tests", + com.android.sdklib.util;x-friends:="com.android.ide.eclipse.tests", com.android.sdklib.xml;x-friends:="com.android.ide.eclipse.tests", com.android.sdkstats;x-friends:="com.android.ide.eclipse.tests", com.android.sdkuilib.internal.repository;x-friends:="com.android.ide.eclipse.tests", diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java index 54ebd42..bfef1f1 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java @@ -18,6 +18,8 @@ package com.android.ide.eclipse.adt; import com.android.ddmuilib.console.DdmConsole; import com.android.ddmuilib.console.IDdmConsole; +import com.android.ide.common.log.ILogger; +import com.android.ide.common.sdk.LoadStatus; import com.android.ide.eclipse.adt.internal.VersionCheck; import com.android.ide.eclipse.adt.internal.editors.IconFactory; import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditor; @@ -35,7 +37,6 @@ import com.android.ide.eclipse.adt.internal.resources.manager.ResourceFolder; import com.android.ide.eclipse.adt.internal.resources.manager.ResourceFolderType; import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager; import com.android.ide.eclipse.adt.internal.resources.manager.GlobalProjectMonitor.IFileListener; -import com.android.ide.eclipse.adt.internal.sdk.LoadStatus; import com.android.ide.eclipse.adt.internal.sdk.Sdk; import com.android.ide.eclipse.adt.internal.sdk.Sdk.ITargetChangeListener; import com.android.ide.eclipse.adt.internal.ui.EclipseUiHelper; @@ -105,7 +106,7 @@ import java.util.List; /** * The activator class controls the plug-in life cycle */ -public class AdtPlugin extends AbstractUIPlugin { +public class AdtPlugin extends AbstractUIPlugin implements ILogger { /** The plug-in ID */ public static final String PLUGIN_ID = "com.android.ide.eclipse.adt"; //$NON-NLS-1$ @@ -1337,4 +1338,22 @@ public class AdtPlugin extends AbstractUIPlugin { } } } + + // --------- ILogger methods ----------- + + public void error(Throwable t, String format, Object... args) { + if (t != null) { + log(t, format, args); + } else { + log(IStatus.ERROR, format, args); + } + } + + public void printf(String format, Object... args) { + log(IStatus.INFO, format, args); + } + + public void warning(String format, Object... args) { + log(IStatus.WARNING, format, args); + } } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AndroidConstants.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AndroidConstants.java index b1ccc28..1c570d2 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AndroidConstants.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AndroidConstants.java @@ -207,8 +207,6 @@ public class AndroidConstants { /** provider value for marker attribute "type" */ public final static String MARKER_ATTR_TYPE_PROVIDER = "provider"; //$NON-NLS-1$ - public final static String CLASS_BRIDGE = "com.android.layoutlib.bridge.Bridge"; //$NON-NLS-1$ - /** * Prefered compiler level, i.e. "1.5". */ diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/BaseBuilder.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/BaseBuilder.java index b143e6b..553ec47 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/BaseBuilder.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/BaseBuilder.java @@ -16,6 +16,7 @@ package com.android.ide.eclipse.adt.internal.build.builders; +import com.android.ide.common.sdk.LoadStatus; import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.AndroidConstants; import com.android.ide.eclipse.adt.internal.build.BuildHelper; @@ -24,7 +25,6 @@ import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper; import com.android.ide.eclipse.adt.internal.project.ProjectHelper; import com.android.ide.eclipse.adt.internal.project.XmlErrorHandler; import com.android.ide.eclipse.adt.internal.project.XmlErrorHandler.XmlErrorListener; -import com.android.ide.eclipse.adt.internal.sdk.LoadStatus; import com.android.ide.eclipse.adt.internal.sdk.Sdk; import com.android.sdklib.IAndroidTarget; diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/IGraphicalLayoutEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/IGraphicalLayoutEditor.java index 04f11a0..d2d778a 100755 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/IGraphicalLayoutEditor.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/IGraphicalLayoutEditor.java @@ -18,7 +18,7 @@ package com.android.ide.eclipse.adt.internal.editors.layout; import com.android.ide.eclipse.adt.internal.editors.uimodel.UiDocumentNode; import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode; -import com.android.layoutlib.api.ILayoutResult; +import com.android.layoutlib.api.LayoutScene; import org.eclipse.core.resources.IFile; import org.eclipse.ui.IEditorPart; @@ -86,7 +86,7 @@ public interface IGraphicalLayoutEditor extends IEditorPart { /** * Renders the given model, using this editor's theme and screen settings, and returns - * the result as an {@link ILayoutResult}. Any error messages will be written to the + * the result as a {@link LayoutScene}. Any error messages will be written to the * editor's error area. * * @param model the model to be rendered, which can be different than the editor's own @@ -94,9 +94,9 @@ public interface IGraphicalLayoutEditor extends IEditorPart { * @param width the width to use for the layout * @param height the height to use for the layout * @param explodeNodes a set of nodes to explode, or null for none - * @return the resulting rendered image wrapped in an {@link ILayoutResult} + * @return the resulting rendered image wrapped in an {@link LayoutScene} */ - abstract ILayoutResult render(UiDocumentNode model, + abstract LayoutScene render(UiDocumentNode model, int width, int height, Set<UiElementNode> explodeNodes); } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite.java index 3d69100..a47bb80 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite.java @@ -16,6 +16,7 @@ package com.android.ide.eclipse.adt.internal.editors.layout.configuration; +import com.android.ide.common.sdk.LoadStatus; import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.internal.resources.ResourceType; import com.android.ide.eclipse.adt.internal.resources.configurations.DockModeQualifier; @@ -35,7 +36,6 @@ import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager; import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData; import com.android.ide.eclipse.adt.internal.sdk.LayoutDevice; import com.android.ide.eclipse.adt.internal.sdk.LayoutDeviceManager; -import com.android.ide.eclipse.adt.internal.sdk.LoadStatus; import com.android.ide.eclipse.adt.internal.sdk.Sdk; import com.android.ide.eclipse.adt.internal.sdk.LayoutDevice.DeviceConfig; import com.android.layoutlib.api.IResourceValue; diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/CanvasViewInfo.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/CanvasViewInfo.java index 7485b6d..bff1606 100755 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/CanvasViewInfo.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/CanvasViewInfo.java @@ -22,8 +22,7 @@ import com.android.ide.eclipse.adt.internal.editors.layout.UiElementPullParser; import com.android.ide.eclipse.adt.internal.editors.layout.uimodel.UiViewElementNode; import com.android.ide.eclipse.adt.internal.editors.uimodel.UiAttributeNode; import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode; -import com.android.layoutlib.api.ILayoutResult; -import com.android.layoutlib.api.ILayoutResult.ILayoutViewInfo; +import com.android.layoutlib.api.ViewInfo; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.ui.views.properties.IPropertyDescriptor; @@ -34,14 +33,14 @@ import org.w3c.dom.Node; import java.util.ArrayList; /** - * Maps a {@link ILayoutViewInfo} in a structure more adapted to our needs. + * Maps a {@link ViewInfo} in a structure more adapted to our needs. * The only large difference is that we keep both the original bounds of the view info * and we pre-compute the selection bounds which are absolute to the rendered image * (whereas the original bounds are relative to the parent view.) * <p/> * Each view also knows its parent and children. * <p/> - * We can't alter {@link ILayoutViewInfo} as it is part of the LayoutBridge and needs to + * We can't alter {@link ViewInfo} as it is part of the LayoutBridge and needs to * have a fixed API. * <p/> * The view info also implements {@link IPropertySource}, which enables a linked @@ -72,21 +71,21 @@ public class CanvasViewInfo implements IPropertySource { private boolean mExploded; /** - * Constructs a {@link CanvasViewInfo} hierarchy based on a given {@link ILayoutViewInfo} + * Constructs a {@link CanvasViewInfo} hierarchy based on a given {@link ViewInfo} * hierarchy. This call is recursive and builds a full tree. * - * @param viewInfo The root of the {@link ILayoutViewInfo} hierarchy. + * @param viewInfo The root of the {@link ViewInfo} hierarchy. */ - public CanvasViewInfo(ILayoutViewInfo viewInfo) { + public CanvasViewInfo(ViewInfo viewInfo) { this(viewInfo, null /*parent*/, 0 /*parentX*/, 0 /*parentY*/); } - private CanvasViewInfo(ILayoutViewInfo viewInfo, CanvasViewInfo parent, + private CanvasViewInfo(ViewInfo viewInfo, CanvasViewInfo parent, int parentX, int parentY) { mParent = parent; - mName = viewInfo.getName(); + mName = viewInfo.getClassName(); - // The ILayoutViewInfo#getViewKey() method returns a key which depends on the + // The ViewInfo#getViewKey() method returns a key which depends on the // IXmlPullParser used to parse the layout files. In this case, the parser is // guaranteed to be an UiElementPullParser, which creates keys that are of type // UiViewElementNode. @@ -107,7 +106,7 @@ public class CanvasViewInfo implements IPropertySource { mAbsRect = new Rectangle(x, y, w - 1, h - 1); if (viewInfo.getChildren() != null) { - for (ILayoutViewInfo child : viewInfo.getChildren()) { + for (ViewInfo child : viewInfo.getChildren()) { // Only use children which have a ViewKey of the correct type. // We can't interact with those when they have a null key or // an incompatible type. @@ -135,7 +134,7 @@ public class CanvasViewInfo implements IPropertySource { } /** - * Returns the original {@link ILayoutResult} bounds in absolute coordinates + * Returns the original {@link ViewInfo} bounds in absolute coordinates * over the whole graphic. */ public Rectangle getAbsRect() { @@ -156,7 +155,7 @@ public class CanvasViewInfo implements IPropertySource { /** * Returns the view key. Could be null, although unlikely. * @return An {@link UiViewElementNode} that uniquely identifies the object in the XML model. - * @see ILayoutViewInfo#getViewKey() + * @see ViewInfo#getViewKey() */ public UiViewElementNode getUiViewKey() { return mUiViewKey; @@ -203,7 +202,7 @@ public class CanvasViewInfo implements IPropertySource { * Could be null, although unlikely. * Experience shows this is the full qualified Java name of the View. * - * @see ILayoutViewInfo#getName() + * @see ViewInfo#getClassName() */ public String getName() { return mName; diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java index fa024af..fd1a31e 100755 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java @@ -16,6 +16,9 @@ package com.android.ide.eclipse.adt.internal.editors.layout.gle2; +import com.android.ide.common.layoutlib.BasicLayoutScene; +import com.android.ide.common.layoutlib.LayoutLibrary; +import com.android.ide.common.sdk.LoadStatus; import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.internal.editors.IconFactory; import com.android.ide.eclipse.adt.internal.editors.layout.ExplodedRenderingHelper; @@ -40,17 +43,15 @@ import com.android.ide.eclipse.adt.internal.resources.manager.ResourceFile; import com.android.ide.eclipse.adt.internal.resources.manager.ResourceFolderType; import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager; import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData; -import com.android.ide.eclipse.adt.internal.sdk.LoadStatus; import com.android.ide.eclipse.adt.internal.sdk.Sdk; -import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData.LayoutBridge; import com.android.ide.eclipse.adt.internal.sdk.Sdk.ITargetChangeListener; import com.android.ide.eclipse.adt.io.IFileWrapper; -import com.android.layoutlib.api.ILayoutBridge; import com.android.layoutlib.api.ILayoutLog; -import com.android.layoutlib.api.ILayoutResult; -import com.android.layoutlib.api.IProjectCallback; import com.android.layoutlib.api.IResourceValue; -import com.android.layoutlib.api.IXmlPullParser; +import com.android.layoutlib.api.LayoutBridge; +import com.android.layoutlib.api.LayoutScene; +import com.android.layoutlib.api.SceneParams; +import com.android.layoutlib.api.SceneResult; import com.android.sdklib.IAndroidTarget; import com.android.sdklib.SdkConstants; import com.android.sdkuilib.internal.widgets.ResolutionChooserDialog; @@ -100,7 +101,6 @@ import org.eclipse.ui.part.EditorPart; import org.eclipse.ui.part.FileEditorInput; import org.w3c.dom.Node; -import java.awt.image.BufferedImage; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -915,8 +915,8 @@ public class GraphicalEditorPart extends EditorPart public void onTargetChange() { AndroidTargetData targetData = mConfigComposite.onXmlModelLoaded(); if (targetData != null) { - LayoutBridge bridge = targetData.getLayoutBridge(); - setClippingSupport(bridge.apiLevel >= 4); + LayoutLibrary layoutLib = targetData.getLayoutLibrary(); + setClippingSupport(layoutLib.getBridge().getApiLevel() >= 4); } mConfigListener.onConfigurationChange(); @@ -1007,41 +1007,26 @@ public class GraphicalEditorPart extends EditorPart // Although we display an error, we still treat an empty document as a // successful layout result so that we can drop new elements in it. // - // For that purpose, create a special ILayoutResult that has no image, + // For that purpose, create a special LayoutScene that has no image, // no root view yet indicates success and then update the canvas with it. - ILayoutResult result = new ILayoutResult() { - public String getErrorMessage() { - return null; - } - - public BufferedImage getImage() { - return null; - } - - public ILayoutViewInfo getRootView() { - return null; - } - - public int getSuccess() { - return ILayoutResult.SUCCESS; - } - }; - - mCanvasViewer.getCanvas().setResult(result, null /*explodeNodes*/); + mCanvasViewer.getCanvas().setResult( + new BasicLayoutScene(SceneResult.SUCCESS, null /*rootViewInfo*/, + null /*image*/), + null /*explodeNodes*/); return; } - LayoutBridge bridge = getReadyBridge(); + LayoutLibrary layoutLib = getReadyLayoutLib(); - if (bridge != null) { + if (layoutLib != null) { // if drawing in real size, (re)set the scaling factor. if (mZoomRealSizeButton.getSelection()) { computeAndSetRealScale(false /* redraw */); } IProject iProject = mEditedFile.getProject(); - renderWithBridge(iProject, model, bridge); + renderWithBridge(iProject, model, layoutLib); } } finally { // no matter the result, we are done doing the recompute based on the latest @@ -1082,14 +1067,14 @@ public class GraphicalEditorPart extends EditorPart } /** - * Returns a {@link LayoutBridge} that is ready for rendering, or null if the bridge + * Returns a {@link LayoutLibrary} that is ready for rendering, or null if the bridge * is not available or not ready yet (due to SDK loading still being in progress etc). * Any reasons preventing the bridge from being returned are displayed to the editor's * error area. * * @return LayoutBridge the layout bridge for rendering this editor's scene */ - private LayoutBridge getReadyBridge() { + private LayoutLibrary getReadyLayoutLib() { Sdk currentSdk = Sdk.getCurrent(); if (currentSdk != null) { IAndroidTarget target = currentSdk.getTarget(mEditedFile.getProject()); @@ -1123,15 +1108,15 @@ public class GraphicalEditorPart extends EditorPart return null; } - LayoutBridge bridge = data.getLayoutBridge(); + LayoutLibrary layoutLib = data.getLayoutLibrary(); - if (bridge.bridge != null) { // bridge can never be null. - return bridge; + if (layoutLib.getBridge() != null) { // layoutLib can never be null. + return layoutLib; } else { // SDK is loaded but not the layout library! // check whether the bridge managed to load, or not - if (bridge.status == LoadStatus.LOADING) { + if (layoutLib.getStatus() == LoadStatus.LOADING) { displayError("Eclipse is loading framework information and the layout library from the SDK folder.\n%1$s will refresh automatically once the process is finished.", mEditedFile.getName()); } else { @@ -1157,7 +1142,8 @@ public class GraphicalEditorPart extends EditorPart return true; } - private void renderWithBridge(IProject iProject, UiDocumentNode model, LayoutBridge bridge) { + private void renderWithBridge(IProject iProject, UiDocumentNode model, + LayoutLibrary layoutLib) { LayoutCanvas canvas = getCanvasControl(); Set<UiElementNode> explodeNodes = canvas.getNodesToExplode(); @@ -1167,14 +1153,15 @@ public class GraphicalEditorPart extends EditorPart int width = rect.width; int height = rect.height; - ILayoutResult result = renderWithBridge(iProject, model, bridge, width, height, explodeNodes); + LayoutScene scene = renderWithBridge(iProject, model, layoutLib, width, height, + explodeNodes); - canvas.setResult(result, explodeNodes); + canvas.setResult(scene, explodeNodes); // update the UiElementNode with the layout info. - if (result.getSuccess() != ILayoutResult.SUCCESS) { + if (scene.getResult() != SceneResult.SUCCESS) { // An error was generated. Print it. - displayError(result.getErrorMessage()); + displayError(scene.getResult().getErrorMessage()); } else { // Success means there was no exception. But we might have detected @@ -1192,7 +1179,7 @@ public class GraphicalEditorPart extends EditorPart model.refreshUi(); } - public ILayoutResult render(UiDocumentNode model, int width, int height, + public LayoutScene render(UiDocumentNode model, int width, int height, Set<UiElementNode> explodeNodes) { if (!ensureFileValid()) { return null; @@ -1200,14 +1187,14 @@ public class GraphicalEditorPart extends EditorPart if (!ensureModelValid(model)) { return null; } - LayoutBridge bridge = getReadyBridge(); + LayoutLibrary layoutLib = getReadyLayoutLib(); IProject iProject = mEditedFile.getProject(); - return renderWithBridge(iProject, model, bridge, width, height, explodeNodes); + return renderWithBridge(iProject, model, layoutLib, width, height, explodeNodes); } - private ILayoutResult renderWithBridge(IProject iProject, UiDocumentNode model, - LayoutBridge bridge, int width, int height, Set<UiElementNode> explodeNodes) { + private LayoutScene renderWithBridge(IProject iProject, UiDocumentNode model, + LayoutLibrary layoutLib, int width, int height, Set<UiElementNode> explodeNodes) { ResourceManager resManager = ResourceManager.getInstance(); ProjectResources projectRes = resManager.getProjectResources(iProject); @@ -1236,7 +1223,7 @@ public class GraphicalEditorPart extends EditorPart // Lazily create the project callback the first time we need it if (mProjectCallback == null) { mProjectCallback = new ProjectCallback( - bridge.classLoader, projectRes, iProject); + layoutLib.getClassLoader(), projectRes, iProject); } else { // Also clears the set of missing classes prior to rendering mProjectCallback.getMissingClasses().clear(); @@ -1295,74 +1282,16 @@ public class GraphicalEditorPart extends EditorPart UiElementPullParser parser = new UiElementPullParser(model, mUseExplodeMode, explodeNodes, density, xdpi, iProject); - ILayoutResult result = computeLayout(bridge, parser, + LayoutScene scene = layoutLib.getBridge().createScene(new SceneParams( + parser, iProject /* projectKey */, width, height, !mClippingButton.getSelection(), density, xdpi, ydpi, theme, isProjectTheme, configuredProjectRes, frameworkResources, mProjectCallback, - mLogger); + mLogger)); - // post rendering clean up - bridge.cleanUp(); - - return result; - } - - /** - * Computes a layout by calling the correct computeLayout method of ILayoutBridge based on - * the implementation API level. - * - * Implementation detail: the bridge's computeLayout() method already returns a newly - * allocated ILayoutResult. - */ - @SuppressWarnings("deprecation") - private static ILayoutResult computeLayout(LayoutBridge bridge, - IXmlPullParser layoutDescription, Object projectKey, - int screenWidth, int screenHeight, boolean renderFullSize, - int density, float xdpi, float ydpi, - String themeName, boolean isProjectTheme, - Map<String, Map<String, IResourceValue>> projectResources, - Map<String, Map<String, IResourceValue>> frameworkResources, - IProjectCallback projectCallback, ILayoutLog logger) { - - if (bridge.apiLevel >= ILayoutBridge.API_CURRENT) { - // newest API with support for "render full height" - // TODO: link boolean to UI. - return bridge.bridge.computeLayout(layoutDescription, - projectKey, screenWidth, screenHeight, renderFullSize, - density, xdpi, ydpi, - themeName, isProjectTheme, - projectResources, frameworkResources, projectCallback, - logger); - } else if (bridge.apiLevel == 3) { - // newer api with density support. - return bridge.bridge.computeLayout(layoutDescription, - projectKey, screenWidth, screenHeight, density, xdpi, ydpi, - themeName, isProjectTheme, - projectResources, frameworkResources, projectCallback, - logger); - } else if (bridge.apiLevel == 2) { - // api with boolean for separation of project/framework theme - return bridge.bridge.computeLayout(layoutDescription, - projectKey, screenWidth, screenHeight, themeName, isProjectTheme, - projectResources, frameworkResources, projectCallback, - logger); - } else { - // oldest api with no density/dpi, and project theme boolean mixed - // into the theme name. - - // change the string if it's a custom theme to make sure we can - // differentiate them - if (isProjectTheme) { - themeName = "*" + themeName; //$NON-NLS-1$ - } - - return bridge.bridge.computeLayout(layoutDescription, - projectKey, screenWidth, screenHeight, themeName, - projectResources, frameworkResources, projectCallback, - logger); - } + return scene; } public Rectangle getBounds() { @@ -1423,10 +1352,10 @@ public class GraphicalEditorPart extends EditorPart AndroidTargetData data = Sdk.getCurrent().getTargetData(target); if (data != null) { - LayoutBridge bridge = data.getLayoutBridge(); + LayoutLibrary layoutLib = data.getLayoutLibrary(); - if (bridge.bridge != null) { - bridge.bridge.clearCaches(mEditedFile.getProject()); + if (layoutLib.getBridge() != null) { + layoutLib.getBridge().clearCaches(mEditedFile.getProject()); } } } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutCanvas.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutCanvas.java index 1c0c798..e313f00 100755 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutCanvas.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutCanvas.java @@ -28,7 +28,7 @@ import com.android.ide.eclipse.adt.internal.editors.layout.gre.RulesEngine; import com.android.ide.eclipse.adt.internal.editors.layout.uimodel.UiViewElementNode; import com.android.ide.eclipse.adt.internal.editors.uimodel.UiDocumentNode; import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode; -import com.android.layoutlib.api.ILayoutResult; +import com.android.layoutlib.api.LayoutScene; import com.android.sdklib.SdkConstants; import org.eclipse.jface.action.Action; @@ -441,20 +441,20 @@ class LayoutCanvas extends Canvas { * allocated ILayourResult. That means we can keep this result and hold on to it * when it is valid. * - * @param result The new rendering result, either valid or not. + * @param scene The new scene, either valid or not. * @param explodedNodes The set of individual nodes the layout computer was asked to * explode. Note that these are independent of the explode-all mode where * all views are exploded; this is used only for the mode ( * {@link #showInvisibleViews(boolean)}) where individual invisible nodes * are padded during certain interactions. */ - /* package */ void setResult(ILayoutResult result, Set<UiElementNode> explodedNodes) { + /* package */ void setResult(LayoutScene scene, Set<UiElementNode> explodedNodes) { // disable any hover clearHover(); - mViewHierarchy.setResult(result, explodedNodes); - if (mViewHierarchy.isValid() && result != null) { - Image image = mImageOverlay.setImage(result.getImage()); + mViewHierarchy.setResult(scene, explodedNodes); + if (mViewHierarchy.isValid() && scene != null) { + Image image = mImageOverlay.setImage(scene.getImage()); mOutlinePage.setModel(mViewHierarchy.getRoot()); diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/ViewHierarchy.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/ViewHierarchy.java index 8c39662..e7c718f 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/ViewHierarchy.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/ViewHierarchy.java @@ -20,8 +20,9 @@ import com.android.ide.common.api.INode; import com.android.ide.eclipse.adt.internal.editors.layout.gre.NodeProxy; import com.android.ide.eclipse.adt.internal.editors.layout.uimodel.UiViewElementNode; import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode; -import com.android.layoutlib.api.ILayoutResult; -import com.android.layoutlib.api.ILayoutResult.ILayoutViewInfo; +import com.android.layoutlib.api.LayoutScene; +import com.android.layoutlib.api.SceneResult; +import com.android.layoutlib.api.ViewInfo; import org.eclipse.swt.graphics.Rectangle; import org.w3c.dom.Node; @@ -63,7 +64,7 @@ public class ViewHierarchy { private CanvasViewInfo mLastValidViewInfoRoot; /** - * True when the last {@link #setResult} provided a valid {@link ILayoutResult}. + * True when the last {@link #setResult} provided a valid {@link LayoutScene}. * <p/> * When false this means the canvas is displaying an out-dated result image & bounds and some * features should be disabled accordingly such a drag'n'drop. @@ -102,23 +103,23 @@ public class ViewHierarchy { * allocated ILayourResult. That means we can keep this result and hold on to it * when it is valid. * - * @param result The new rendering result, either valid or not. + * @param scene The new result, either valid or not. * @param explodedNodes The set of individual nodes the layout computer was asked to * explode. Note that these are independent of the explode-all mode where * all views are exploded; this is used only for the mode ( * {@link LayoutCanvas#showInvisibleViews}) where individual invisible * nodes are padded during certain interactions. */ - /* package */ void setResult(ILayoutResult result, Set<UiElementNode> explodedNodes) { - mIsResultValid = (result != null && result.getSuccess() == ILayoutResult.SUCCESS); + /* package */ void setResult(LayoutScene scene, Set<UiElementNode> explodedNodes) { + mIsResultValid = (scene != null && scene.getResult() == SceneResult.SUCCESS); mExplodedParents = false; - if (mIsResultValid && result != null) { - ILayoutViewInfo root = result.getRootView(); + if (mIsResultValid && scene != null) { + ViewInfo root = scene.getRootView(); if (root == null) { mLastValidViewInfoRoot = null; } else { - mLastValidViewInfoRoot = new CanvasViewInfo(result.getRootView()); + mLastValidViewInfoRoot = new CanvasViewInfo(scene.getRootView()); } updateNodeProxies(mLastValidViewInfoRoot); @@ -202,7 +203,7 @@ public class ViewHierarchy { /** * Returns true when the last {@link #setResult} provided a valid - * {@link ILayoutResult}. + * {@link LayoutScene}. * <p/> * When false this means the canvas is displaying an out-dated result image & bounds and some * features should be disabled accordingly such a drag'n'drop. diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/AndroidClasspathContainerInitializer.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/AndroidClasspathContainerInitializer.java index 9ee286e..a1b11ae 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/AndroidClasspathContainerInitializer.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/AndroidClasspathContainerInitializer.java @@ -16,9 +16,9 @@ package com.android.ide.eclipse.adt.internal.project; +import com.android.ide.common.sdk.LoadStatus; import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.AndroidConstants; -import com.android.ide.eclipse.adt.internal.sdk.LoadStatus; import com.android.ide.eclipse.adt.internal.sdk.ProjectState; import com.android.ide.eclipse.adt.internal.sdk.Sdk; import com.android.sdklib.AndroidVersion; diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/MultiResourceFile.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/MultiResourceFile.java index 012f3dd..ae56f67 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/MultiResourceFile.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/MultiResourceFile.java @@ -16,11 +16,11 @@ package com.android.ide.eclipse.adt.internal.resources.manager; +import com.android.ide.common.layoutlib.ResourceValue; +import com.android.ide.common.layoutlib.ValueResourceParser; +import com.android.ide.common.layoutlib.ValueResourceParser.IValueResourceRepository; import com.android.ide.eclipse.adt.internal.resources.ResourceType; import com.android.layoutlib.api.IResourceValue; -import com.android.layoutlib.utils.ResourceValue; -import com.android.layoutlib.utils.ValueResourceParser; -import com.android.layoutlib.utils.ValueResourceParser.IValueResourceRepository; import com.android.sdklib.io.IAbstractFile; import com.android.sdklib.io.StreamException; diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ProjectResources.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ProjectResources.java index ae6e06b..36ce3b0 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ProjectResources.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ProjectResources.java @@ -16,6 +16,7 @@ package com.android.ide.eclipse.adt.internal.resources.manager; +import com.android.ide.common.layoutlib.ResourceValue; import com.android.ide.eclipse.adt.internal.resources.IResourceRepository; import com.android.ide.eclipse.adt.internal.resources.ResourceItem; import com.android.ide.eclipse.adt.internal.resources.ResourceType; @@ -27,7 +28,6 @@ import com.android.ide.eclipse.adt.internal.sdk.ProjectState; import com.android.ide.eclipse.adt.internal.sdk.Sdk; import com.android.ide.eclipse.adt.io.IFolderWrapper; import com.android.layoutlib.api.IResourceValue; -import com.android.layoutlib.utils.ResourceValue; import com.android.sdklib.io.IAbstractFolder; import org.eclipse.core.resources.IFolder; diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/SingleResourceFile.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/SingleResourceFile.java index f17c397..637d20b 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/SingleResourceFile.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/SingleResourceFile.java @@ -16,12 +16,12 @@ package com.android.ide.eclipse.adt.internal.resources.manager; +import com.android.ide.common.layoutlib.DensityBasedResourceValue; +import com.android.ide.common.layoutlib.ResourceValue; import com.android.ide.eclipse.adt.internal.resources.ResourceType; import com.android.ide.eclipse.adt.internal.resources.configurations.PixelDensityQualifier; import com.android.layoutlib.api.IResourceValue; import com.android.layoutlib.api.IDensityBasedResourceValue.Density; -import com.android.layoutlib.utils.DensityBasedResourceValue; -import com.android.layoutlib.utils.ResourceValue; import com.android.sdklib.io.IAbstractFile; import java.util.ArrayList; diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidTargetData.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidTargetData.java index a9dc43e..3667d3f 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidTargetData.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidTargetData.java @@ -16,7 +16,8 @@ package com.android.ide.eclipse.adt.internal.sdk; -import com.android.ide.eclipse.adt.AdtPlugin; +import com.android.ide.common.layoutlib.LayoutLibrary; +import com.android.ide.common.sdk.LoadStatus; import com.android.ide.eclipse.adt.internal.editors.descriptors.IDescriptorProvider; import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.LayoutDescriptors; import com.android.ide.eclipse.adt.internal.editors.manifest.descriptors.AndroidManifestDescriptors; @@ -25,11 +26,10 @@ import com.android.ide.eclipse.adt.internal.editors.resources.descriptors.Resour import com.android.ide.eclipse.adt.internal.editors.xml.descriptors.XmlDescriptors; import com.android.ide.eclipse.adt.internal.resources.IResourceRepository; import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources; -import com.android.layoutlib.api.ILayoutBridge; +import com.android.layoutlib.api.LayoutBridge; import com.android.sdklib.IAndroidTarget; import com.android.sdklib.IAndroidTarget.IOptionalLibrary; -import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Hashtable; import java.util.Map; @@ -48,40 +48,6 @@ public class AndroidTargetData { public final static int DESCRIPTOR_PREFERENCES = 7; public final static int DESCRIPTOR_APPWIDGET_PROVIDER = 8; - public final static class LayoutBridge { - /** Link to the layout bridge */ - public ILayoutBridge bridge; - - public LoadStatus status = LoadStatus.LOADING; - - public ClassLoader classLoader; - - public int apiLevel; - - /** - * Post rendering clean-up that must be done here so that it's done even for older - * versions of the layoutlib. - */ - public void cleanUp() { - if (apiLevel <= 4) { - try { - Class<?> looperClass = classLoader.loadClass("android.os.Looper"); //$NON-NLS-1$ - Field threadLocalField = looperClass.getField("sThreadLocal"); //$NON-NLS-1$ - if (threadLocalField != null) { - threadLocalField.setAccessible(true); - // get object. Field is static so no need to pass an object - ThreadLocal<?> threadLocal = (ThreadLocal<?>) threadLocalField.get(null); - if (threadLocal != null) { - threadLocal.remove(); - } - } - } catch (Exception e) { - AdtPlugin.log(e, "Failed to clean up bridge for API level %d", apiLevel); - } - } - } - } - private final IAndroidTarget mTarget; /** @@ -106,7 +72,7 @@ public class AndroidTargetData { private Map<String, Map<String, Integer>> mEnumValueMap; private ProjectResources mFrameworkResources; - private LayoutBridge mLayoutBridge; + private LayoutLibrary mLayoutLibrary; private boolean mLayoutBridgeInit = false; @@ -133,7 +99,7 @@ public class AndroidTargetData { String[] platformLibraries, IOptionalLibrary[] optionalLibraries, ProjectResources resources, - LayoutBridge layoutBridge) { + LayoutLibrary layoutLibrary) { mSystemResourceRepository = systemResourceRepository; mManifestDescriptors = manifestDescriptors; @@ -142,7 +108,7 @@ public class AndroidTargetData { mXmlDescriptors = xmlDescriptors; mEnumValueMap = enumValueMap; mFrameworkResources = resources; - mLayoutBridge = layoutBridge; + mLayoutLibrary = layoutLibrary; setPermissions(permissionValues); setIntentFilterActionsAndCategories(activityIntentActionValues, broadcastIntentActionValues, @@ -274,18 +240,19 @@ public class AndroidTargetData { } /** - * Returns a {@link LayoutBridge} object possibly containing a {@link ILayoutBridge} object. - * <p/>If {@link LayoutBridge#bridge} is <code>null</code>, {@link LayoutBridge#status} will - * contain the reason (either {@link LoadStatus#LOADING} or {@link LoadStatus#FAILED}). - * <p/>Valid {@link ILayoutBridge} objects are always initialized before being returned. + * Returns a {@link LayoutLibrary} object possibly containing a {@link LayoutBridge} object. + * <p/>If {@link LayoutLibrary#getBridge()} is <code>null</code>, + * {@link LayoutBridge#getStatus()} will contain the reason (either {@link LoadStatus#LOADING} + * or {@link LoadStatus#FAILED}). + * <p/>Valid {@link LayoutBridge} objects are always initialized before being returned. */ - public synchronized LayoutBridge getLayoutBridge() { - if (mLayoutBridgeInit == false && mLayoutBridge.bridge != null) { - mLayoutBridge.bridge.init(mTarget.getPath(IAndroidTarget.FONTS), + public synchronized LayoutLibrary getLayoutLibrary() { + if (mLayoutBridgeInit == false && mLayoutLibrary.getBridge() != null) { + mLayoutLibrary.getBridge().init(mTarget.getPath(IAndroidTarget.FONTS), getEnumValueMap()); mLayoutBridgeInit = true; } - return mLayoutBridge; + return mLayoutLibrary; } /** diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidTargetParser.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidTargetParser.java index 9c273fb..05b1769 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidTargetParser.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidTargetParser.java @@ -16,8 +16,8 @@ package com.android.ide.eclipse.adt.internal.sdk; +import com.android.ide.common.layoutlib.LayoutLibrary; import com.android.ide.eclipse.adt.AdtPlugin; -import com.android.ide.eclipse.adt.AndroidConstants; import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.LayoutDescriptors; import com.android.ide.eclipse.adt.internal.editors.manifest.descriptors.AndroidManifestDescriptors; import com.android.ide.eclipse.adt.internal.editors.menu.descriptors.MenuDescriptors; @@ -30,8 +30,6 @@ import com.android.ide.eclipse.adt.internal.resources.ResourceType; import com.android.ide.eclipse.adt.internal.resources.ViewClassInfo; import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources; import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager; -import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData.LayoutBridge; -import com.android.layoutlib.api.ILayoutBridge; import com.android.sdklib.IAndroidTarget; import com.android.sdklib.SdkConstants; @@ -41,16 +39,11 @@ import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubMonitor; import java.io.BufferedReader; -import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; -import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Modifier; -import java.net.URI; -import java.net.URL; -import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -241,7 +234,10 @@ public final class AndroidTargetParser { progress.worked(1); // now load the layout lib bridge - LayoutBridge layoutBridge = loadLayoutBridge(); + LayoutLibrary layoutBridge = LayoutLibrary.load( + mAndroidTarget.getPath(IAndroidTarget.LAYOUT_LIB), + AdtPlugin.getDefault()); + progress.worked(1); // and finally create the PlatformData with all that we loaded. @@ -635,62 +631,4 @@ public final class AndroidTargetParser { return attrsXmlParser.getDeclareStyleableList(); } - /** - * Loads the layout bridge from the dynamically loaded layoutlib.jar - */ - private LayoutBridge loadLayoutBridge() { - LayoutBridge layoutBridge = new LayoutBridge(); - - try { - // get the URL for the file. - File f = new File(mAndroidTarget.getPath(IAndroidTarget.LAYOUT_LIB)); - if (f.isFile() == false) { - AdtPlugin.log(IStatus.ERROR, "layoutlib.jar is missing!"); //$NON-NLS-1$ - } else { - URI uri = f.toURI(); - URL url = uri.toURL(); - - // create a class loader. Because this jar reference interfaces - // that are in the editors plugin, it's important to provide - // a parent class loader. - layoutBridge.classLoader = new URLClassLoader(new URL[] { url }, - this.getClass().getClassLoader()); - - // load the class - Class<?> clazz = layoutBridge.classLoader.loadClass(AndroidConstants.CLASS_BRIDGE); - if (clazz != null) { - // instantiate an object of the class. - Constructor<?> constructor = clazz.getConstructor(); - if (constructor != null) { - Object bridge = constructor.newInstance(); - if (bridge instanceof ILayoutBridge) { - layoutBridge.bridge = (ILayoutBridge)bridge; - } - } - } - - if (layoutBridge.bridge == null) { - layoutBridge.status = LoadStatus.FAILED; - AdtPlugin.log(IStatus.ERROR, "Failed to load " + AndroidConstants.CLASS_BRIDGE); //$NON-NLS-1$ - } else { - // get the api level - try { - layoutBridge.apiLevel = layoutBridge.bridge.getApiLevel(); - } catch (AbstractMethodError e) { - // the first version of the api did not have this method - layoutBridge.apiLevel = 1; - } - - // and mark the lib as loaded. - layoutBridge.status = LoadStatus.LOADED; - } - } - } catch (Throwable t) { - layoutBridge.status = LoadStatus.FAILED; - // log the error. - AdtPlugin.log(t, "Failed to load the LayoutLib"); - } - - return layoutBridge; - } } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java index d2f00da..e75b846 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java @@ -17,6 +17,8 @@ package com.android.ide.eclipse.adt.internal.sdk; import com.android.ddmlib.IDevice; +import com.android.ide.common.layoutlib.LayoutLibrary; +import com.android.ide.common.sdk.LoadStatus; import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.AndroidConstants; import com.android.ide.eclipse.adt.internal.build.DexWrapper; @@ -27,7 +29,6 @@ import com.android.ide.eclipse.adt.internal.resources.manager.GlobalProjectMonit import com.android.ide.eclipse.adt.internal.resources.manager.GlobalProjectMonitor.IFileListener; import com.android.ide.eclipse.adt.internal.resources.manager.GlobalProjectMonitor.IProjectListener; import com.android.ide.eclipse.adt.internal.resources.manager.GlobalProjectMonitor.IResourceEventListener; -import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData.LayoutBridge; import com.android.ide.eclipse.adt.internal.sdk.ProjectState.LibraryDifference; import com.android.ide.eclipse.adt.internal.sdk.ProjectState.LibraryState; import com.android.prefs.AndroidLocation.AndroidLocationException; @@ -764,9 +765,9 @@ public final class Sdk { // get the bridge for the target, and clear the cache for this project. AndroidTargetData data = mTargetDataMap.get(target); if (data != null) { - LayoutBridge bridge = data.getLayoutBridge(); - if (bridge != null && bridge.status == LoadStatus.LOADED) { - bridge.bridge.clearCaches(project); + LayoutLibrary layoutLib = data.getLayoutLibrary(); + if (layoutLib != null && layoutLib.getStatus() == LoadStatus.LOADED) { + layoutLib.getBridge().clearCaches(project); } } } diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/.classpath b/eclipse/plugins/com.android.ide.eclipse.tests/.classpath index 9164986..0702e99 100644 --- a/eclipse/plugins/com.android.ide.eclipse.tests/.classpath +++ b/eclipse/plugins/com.android.ide.eclipse.tests/.classpath @@ -7,6 +7,7 @@ <classpathentry kind="lib" path="layoutlib.jar"/> <classpathentry kind="lib" path="kxml2-2.3.0.jar"/> <classpathentry kind="lib" path="easymock.jar"/> + <classpathentry kind="lib" path="layoutlib_utils.jar"/> <classpathentry combineaccessrules="false" kind="src" path="/ddmlib"/> <classpathentry combineaccessrules="false" kind="src" path="/ddmuilib"/> <classpathentry kind="lib" path="/adt/libs/layoutlib_api.jar" sourcepath="/layoutlib_api"/> diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/SdkTestCase.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/SdkTestCase.java index 9862ba2..2774557 100644 --- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/SdkTestCase.java +++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/SdkTestCase.java @@ -15,9 +15,9 @@ */ package com.android.ide.eclipse.tests; +import com.android.ide.common.sdk.LoadStatus; import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetParser; -import com.android.ide.eclipse.adt.internal.sdk.LoadStatus; import com.android.ide.eclipse.adt.internal.sdk.Sdk; import com.android.sdklib.IAndroidTarget; diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/functests/layoutRendering/ApiDemosRenderingTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/functests/layoutRendering/ApiDemosRenderingTest.java index 6045daf..b7d648a 100644 --- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/functests/layoutRendering/ApiDemosRenderingTest.java +++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/functests/layoutRendering/ApiDemosRenderingTest.java @@ -16,6 +16,8 @@ package com.android.ide.eclipse.tests.functests.layoutRendering; +import com.android.ide.common.layoutlib.LayoutLibrary; +import com.android.ide.common.sdk.LoadStatus; import com.android.ide.eclipse.adt.internal.resources.configurations.FolderConfiguration; import com.android.ide.eclipse.adt.internal.resources.configurations.KeyboardStateQualifier; import com.android.ide.eclipse.adt.internal.resources.configurations.NavigationMethodQualifier; @@ -29,13 +31,15 @@ import com.android.ide.eclipse.adt.internal.resources.configurations.TouchScreen import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources; import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager; import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData; -import com.android.ide.eclipse.adt.internal.sdk.LoadStatus; -import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData.LayoutBridge; import com.android.ide.eclipse.tests.SdkTestCase; import com.android.layoutlib.api.ILayoutResult; import com.android.layoutlib.api.IProjectCallback; import com.android.layoutlib.api.IResourceValue; import com.android.layoutlib.api.IXmlPullParser; +import com.android.layoutlib.api.LayoutScene; +import com.android.layoutlib.api.SceneParams; +import com.android.layoutlib.api.SceneResult; +import com.android.layoutlib.api.SceneResult.LayoutStatus; import com.android.sdklib.IAndroidTarget; import com.android.sdklib.SdkConstants; import com.android.sdklib.io.FolderWrapper; @@ -151,8 +155,8 @@ public class ApiDemosRenderingTest extends SdkTestCase { fail("No AndroidData!"); } - LayoutBridge bridge = data.getLayoutBridge(); - if (bridge.status != LoadStatus.LOADED || bridge.bridge == null) { + LayoutLibrary layoutLib = data.getLayoutLibrary(); + if (layoutLib.getStatus() != LoadStatus.LOADED || layoutLib.getBridge() == null) { fail("Fail to load the bridge"); } @@ -197,7 +201,7 @@ public class ApiDemosRenderingTest extends SdkTestCase { ProjectCallBack projectCallBack = new ProjectCallBack(); - ILayoutResult result = bridge.bridge.computeLayout( + LayoutScene scene = layoutLib.getBridge().createScene(new SceneParams( parser, null /*projectKey*/, 320, @@ -212,20 +216,20 @@ public class ApiDemosRenderingTest extends SdkTestCase { configuredFramework, projectCallBack, null //logger - ); + )); - if (result.getSuccess() != ILayoutResult.SUCCESS) { + if (scene.getResult() != SceneResult.SUCCESS) { if (projectCallBack.mCustomViewAttempt == false) { System.out.println("FAILED"); fail(String.format("Rendering %1$s: %2$s", layout.getName(), - result.getErrorMessage())); + scene.getResult().getErrorMessage())); } else { System.out.println("Ignore custom views for now"); } } else { if (saveFiles) { File tmp = File.createTempFile(layout.getName(), ".png"); - ImageIO.write(result.getImage(), "png", tmp); + ImageIO.write(scene.getImage(), "png", tmp); } System.out.println("Success!"); } diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/editors/layout/gre/NodeFactoryTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/editors/layout/gre/NodeFactoryTest.java index 9d622e0..ad39fe6 100755 --- a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/editors/layout/gre/NodeFactoryTest.java +++ b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/editors/layout/gre/NodeFactoryTest.java @@ -21,7 +21,7 @@ import com.android.ide.common.api.Rect; import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.ViewElementDescriptor; import com.android.ide.eclipse.adt.internal.editors.layout.gle2.CanvasViewInfo; import com.android.ide.eclipse.adt.internal.editors.layout.uimodel.UiViewElementNode; -import com.android.layoutlib.api.ILayoutResult.ILayoutViewInfo; +import com.android.layoutlib.api.ViewInfo; import java.util.Arrays; @@ -47,7 +47,7 @@ public class NodeFactoryTest extends TestCase { public final void testCreateCanvasViewInfo() { ViewElementDescriptor ved = new ViewElementDescriptor("xml", "com.example.MyJavaClass"); UiViewElementNode uiv = new UiViewElementNode(ved); - MockLayoutViewInfo lvi = new MockLayoutViewInfo(uiv, "name", 10, 12, 110, 120); + ViewInfo lvi = new ViewInfo("name", uiv, 10, 12, 110, 120); CanvasViewInfo cvi = new CanvasViewInfo(lvi); // Create a NodeProxy. @@ -94,7 +94,7 @@ public class NodeFactoryTest extends TestCase { public final void testCreateDup() { ViewElementDescriptor ved = new ViewElementDescriptor("xml", "com.example.MyJavaClass"); UiViewElementNode uiv = new UiViewElementNode(ved); - MockLayoutViewInfo lvi = new MockLayoutViewInfo(uiv, "name", 10, 12, 110, 120); + ViewInfo lvi = new ViewInfo("name", uiv, 10, 12, 110, 120); CanvasViewInfo cvi = new CanvasViewInfo(lvi); // NodeProxies are cached. Creating the same one twice returns the same proxy. @@ -106,7 +106,7 @@ public class NodeFactoryTest extends TestCase { public final void testClear() { ViewElementDescriptor ved = new ViewElementDescriptor("xml", "com.example.MyJavaClass"); UiViewElementNode uiv = new UiViewElementNode(ved); - MockLayoutViewInfo lvi = new MockLayoutViewInfo(uiv, "name", 10, 12, 110, 120); + ViewInfo lvi = new ViewInfo("name", uiv, 10, 12, 110, 120); CanvasViewInfo cvi = new CanvasViewInfo(lvi); // NodeProxies are cached. Creating the same one twice returns the same proxy. @@ -120,58 +120,4 @@ public class NodeFactoryTest extends TestCase { assertNotSame(proxy1, proxy3); } - private static class MockLayoutViewInfo implements ILayoutViewInfo { - private final Object mViewKey; - private final String mName; - private final int mLeft; - private final int mTop; - private final int mRight; - private final int mBottom; - - public MockLayoutViewInfo( - Object viewKey, - String name, - int left, - int top, - int right, - int bottom) { - mViewKey = viewKey; - mName = name; - mLeft = left; - mTop = top; - mRight = right; - mBottom = bottom; - } - - - public ILayoutViewInfo[] getChildren() { - return null; - } - - public Object getViewKey() { - return mViewKey; - } - - public String getName() { - return mName; - } - - public int getLeft() { - return mLeft; - } - - public int getTop() { - return mTop; - } - - public int getRight() { - return mRight; - } - - - public int getBottom() { - return mBottom; - } - } - } diff --git a/eclipse/scripts/create_test_symlinks.sh b/eclipse/scripts/create_test_symlinks.sh index dca9bf3..17f2707 100755 --- a/eclipse/scripts/create_test_symlinks.sh +++ b/eclipse/scripts/create_test_symlinks.sh @@ -35,7 +35,7 @@ BASE="sdk/eclipse/plugins/com.android.ide.eclipse.tests" DEST=$BASE BACK=`back $DEST` -LIBS="easymock" +LIBS="easymock layoutlib_utils" echo "make java libs ..." make -j3 showcommands $LIBS || die "ADT: Fail to build one of $LIBS." diff --git a/layoutlib_api/src/com/android/layoutlib/api/SceneResult.java b/layoutlib_api/src/com/android/layoutlib/api/SceneResult.java index 7214b3f..386eecc 100644 --- a/layoutlib_api/src/com/android/layoutlib/api/SceneResult.java +++ b/layoutlib_api/src/com/android/layoutlib/api/SceneResult.java @@ -29,13 +29,9 @@ public class SceneResult { public enum LayoutStatus { SUCCESS, ERROR, NOT_IMPLEMENTED }; /** - * Creates a successful {@link SceneResult} object. + * Singleton SUCCESS {@link SceneResult} object. */ - public SceneResult() { - mStatus = LayoutStatus.SUCCESS; - mErrorMessage = null; - mThrowable = null; - } + public static final SceneResult SUCCESS = new SceneResult(LayoutStatus.SUCCESS); /** * Creates an error {@link SceneResult} object with the given message. diff --git a/layoutlib_api/src/com/android/layoutlib/api/ViewInfo.java b/layoutlib_api/src/com/android/layoutlib/api/ViewInfo.java index 3e7d907..d991cc8 100644 --- a/layoutlib_api/src/com/android/layoutlib/api/ViewInfo.java +++ b/layoutlib_api/src/com/android/layoutlib/api/ViewInfo.java @@ -16,7 +16,6 @@ package com.android.layoutlib.api; -import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; @@ -32,7 +31,7 @@ public class ViewInfo { protected final int mRight; protected final int mTop; protected final int mBottom; - protected List<ViewInfo> mChildren;; + protected List<ViewInfo> mChildren = Collections.emptyList(); public ViewInfo(String name, Object key, int left, int top, int right, int bottom) { mName = name; @@ -47,9 +46,7 @@ public class ViewInfo { * Sets the list of children {@link ViewInfo}. */ public void setChildren(List<ViewInfo> children) { - mChildren = new ArrayList<ViewInfo>(); - mChildren.addAll(children); - mChildren = Collections.unmodifiableList(mChildren); + mChildren = Collections.unmodifiableList(children); } /** @@ -65,42 +62,42 @@ public class ViewInfo { * @see IXmlPullParser#getViewKey() */ public Object getViewKey() { - return null; + return mKey; } /** * Returns the class name of the view object. Can be null. */ public String getClassName() { - return null; + return mName; } /** * Returns the left of the view bounds, relative to the view parent bounds. */ public int getLeft() { - return 0; + return mLeft; } /** * Returns the top of the view bounds, relative to the view parent bounds. */ public int getTop() { - return 0; + return mTop; } /** * Returns the right of the view bounds, relative to the view parent bounds. */ public int getRight() { - return 0; + return mRight; } /** * Returns the bottom of the view bounds, relative to the view parent bounds. */ public int getBottom() { - return 0; + return mBottom; } /** diff --git a/layoutlib_utils/src/com/android/ide/common/layoutlib/BasicLayoutScene.java b/layoutlib_utils/src/com/android/ide/common/layoutlib/BasicLayoutScene.java new file mode 100644 index 0000000..dfb3992 --- /dev/null +++ b/layoutlib_utils/src/com/android/ide/common/layoutlib/BasicLayoutScene.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2010 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.ide.common.layoutlib; + +import com.android.layoutlib.api.LayoutScene; +import com.android.layoutlib.api.SceneResult; +import com.android.layoutlib.api.ViewInfo; + +import java.awt.image.BufferedImage; + +/** + * Basic LayoutScene returning a given {@link SceneResult}, {@link ViewInfo} and + * {@link BufferedImage}. + * <p/> + * All other methods are untouched from the base implementation provided by the API. + * + */ +public class BasicLayoutScene extends LayoutScene { + + private final SceneResult mResult; + private final ViewInfo mRootViewInfo; + private final BufferedImage mImage; + + public BasicLayoutScene(SceneResult result, ViewInfo rootViewInfo, BufferedImage image) { + mResult = result; + mRootViewInfo = rootViewInfo; + mImage = image; + } + + @Override + public SceneResult getResult() { + return mResult; + } + + @Override + public ViewInfo getRootView() { + return mRootViewInfo; + } + + @Override + public BufferedImage getImage() { + return mImage; + } +} diff --git a/layoutlib_utils/src/com/android/layoutlib/utils/DensityBasedResourceValue.java b/layoutlib_utils/src/com/android/ide/common/layoutlib/DensityBasedResourceValue.java index 59de463..e1c0caa 100644 --- a/layoutlib_utils/src/com/android/layoutlib/utils/DensityBasedResourceValue.java +++ b/layoutlib_utils/src/com/android/ide/common/layoutlib/DensityBasedResourceValue.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.layoutlib.utils; +package com.android.ide.common.layoutlib; import com.android.layoutlib.api.IDensityBasedResourceValue; diff --git a/layoutlib_utils/src/com/android/ide/common/layoutlib/LayoutBridgeWrapper.java b/layoutlib_utils/src/com/android/ide/common/layoutlib/LayoutBridgeWrapper.java new file mode 100644 index 0000000..f4c99bd --- /dev/null +++ b/layoutlib_utils/src/com/android/ide/common/layoutlib/LayoutBridgeWrapper.java @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2010 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.ide.common.layoutlib; + +import com.android.layoutlib.api.ILayoutBridge; +import com.android.layoutlib.api.ILayoutResult; +import com.android.layoutlib.api.LayoutBridge; +import com.android.layoutlib.api.LayoutScene; +import com.android.layoutlib.api.SceneParams; +import com.android.layoutlib.api.SceneResult; +import com.android.layoutlib.api.ViewInfo; +import com.android.layoutlib.api.ILayoutResult.ILayoutViewInfo; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Map; + +/** + * {@link LayoutBridge} wrapper around a {@link ILayoutBridge}. + * <p/> + * The goal is to let tools only uses the latest API by providing a conversion interface + * between the really old API ({@link ILayoutBridge}) and the new one ({@link ILayoutBridge}). + * + */ +@SuppressWarnings("deprecation") +class LayoutBridgeWrapper extends LayoutBridge { + + private final ILayoutBridge mBridge; + private final ClassLoader mClassLoader; + + LayoutBridgeWrapper(ILayoutBridge bridge, ClassLoader classLoader) { + mBridge = bridge; + mClassLoader = classLoader; + } + + @Override + public int getApiLevel() { + int apiLevel = 1; + try { + apiLevel = mBridge.getApiLevel(); + } catch (AbstractMethodError e) { + // the first version of the api did not have this method + // so this is 1 + } + + return apiLevel; + } + + @Override + public boolean init(String fontOsLocation, Map<String, Map<String, Integer>> enumValueMap) { + return mBridge.init(fontOsLocation, enumValueMap); + } + + @Override + public boolean dispose() { + // there's no dispose in ILayoutBridge + return true; + } + + + @Override + public LayoutScene createScene(SceneParams params) { + int apiLevel = mBridge.getApiLevel(); + + ILayoutResult result = null; + + if (apiLevel == 4) { + // Final ILayoutBridge API added support for "render full height" + result = mBridge.computeLayout( + params.getLayoutDescription(), params.getProjectKey(), + params.getScreenWidth(), params.getScreenHeight(), params.getRenderFullSize(), + params.getDensity(), params.getXdpi(), params.getYdpi(), + params.getThemeName(), params.getIsProjectTheme(), + params.getProjectResources(), params.getFrameworkResources(), + params.getProjectCallback(), params.getLogger()); + } else if (apiLevel == 3) { + // api 3 add density support. + result = mBridge.computeLayout( + params.getLayoutDescription(), params.getProjectKey(), + params.getScreenWidth(), params.getScreenHeight(), + params.getDensity(), params.getXdpi(), params.getYdpi(), + params.getThemeName(), params.getIsProjectTheme(), + params.getProjectResources(), params.getFrameworkResources(), + params.getProjectCallback(), params.getLogger()); + } else if (apiLevel == 2) { + // api 2 added boolean for separation of project/framework theme + result = mBridge.computeLayout( + params.getLayoutDescription(), params.getProjectKey(), + params.getScreenWidth(), params.getScreenHeight(), + params.getThemeName(), params.getIsProjectTheme(), + params.getProjectResources(), params.getFrameworkResources(), + params.getProjectCallback(), params.getLogger()); + } else { + // First api with no density/dpi, and project theme boolean mixed + // into the theme name. + + // change the string if it's a custom theme to make sure we can + // differentiate them + String themeName = params.getThemeName(); + if (params.getIsProjectTheme()) { + themeName = "*" + themeName; //$NON-NLS-1$ + } + + result = mBridge.computeLayout( + params.getLayoutDescription(), params.getProjectKey(), + params.getScreenWidth(), params.getScreenHeight(), + themeName, + params.getProjectResources(), params.getFrameworkResources(), + params.getProjectCallback(), params.getLogger()); + } + + // clean up that is not done by the ILayoutBridge itself + cleanUp(); + + return convertToScene(result); + } + + + @Override + public void clearCaches(Object projectKey) { + mBridge.clearCaches(projectKey); + } + + /** + * Converts a {@link ILayoutResult} to a {@link LayoutScene}. + */ + private LayoutScene convertToScene(ILayoutResult result) { + + SceneResult sceneResult; + ViewInfo rootViewInfo; + + if (result.getSuccess() == ILayoutResult.SUCCESS) { + sceneResult = SceneResult.SUCCESS; + rootViewInfo = convertToViewInfo(result.getRootView()); + } else { + sceneResult = new SceneResult(result.getErrorMessage()); + rootViewInfo = null; + } + + // create a BasicLayoutScene. This will return the given values but return the default + // implementation for all method. + // ADT should gracefully handle the default implementations of LayoutScene + return new BasicLayoutScene(sceneResult, rootViewInfo, result.getImage()); + } + + /** + * Converts a {@link ILayoutViewInfo} (and its children) to a {@link ViewInfo}. + */ + private ViewInfo convertToViewInfo(ILayoutViewInfo view) { + // create the view info. + ViewInfo viewInfo = new ViewInfo(view.getName(), view.getViewKey(), + view.getLeft(), view.getTop(), view.getRight(), view.getBottom()); + + // then convert the children + ILayoutViewInfo[] children = view.getChildren(); + if (children != null) { + ArrayList<ViewInfo> convertedChildren = new ArrayList<ViewInfo>(children.length); + for (ILayoutViewInfo child : children) { + convertedChildren.add(convertToViewInfo(child)); + } + viewInfo.setChildren(convertedChildren); + } + + return viewInfo; + } + + /** + * Post rendering clean-up that must be done here because it's not done in any layoutlib using + * {@link ILayoutBridge}. + */ + private void cleanUp() { + try { + Class<?> looperClass = mClassLoader.loadClass("android.os.Looper"); //$NON-NLS-1$ + Field threadLocalField = looperClass.getField("sThreadLocal"); //$NON-NLS-1$ + if (threadLocalField != null) { + threadLocalField.setAccessible(true); + // get object. Field is static so no need to pass an object + ThreadLocal<?> threadLocal = (ThreadLocal<?>) threadLocalField.get(null); + if (threadLocal != null) { + threadLocal.remove(); + } + } + } catch (Exception e) { + // do nothing. + } + } +} diff --git a/layoutlib_utils/src/com/android/ide/common/layoutlib/LayoutLibrary.java b/layoutlib_utils/src/com/android/ide/common/layoutlib/LayoutLibrary.java new file mode 100644 index 0000000..5ec7ae5 --- /dev/null +++ b/layoutlib_utils/src/com/android/ide/common/layoutlib/LayoutLibrary.java @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2010 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.ide.common.layoutlib; + +import com.android.ide.common.log.ILogger; +import com.android.ide.common.sdk.LoadStatus; +import com.android.layoutlib.api.ILayoutBridge; +import com.android.layoutlib.api.LayoutBridge; + +import java.io.File; +import java.lang.reflect.Constructor; +import java.net.URI; +import java.net.URL; +import java.net.URLClassLoader; + +/** + * Class representing and allowing to load the layoutlib jar file. + */ +@SuppressWarnings("deprecation") +public class LayoutLibrary { + + public final static String CLASS_BRIDGE = "com.android.layoutlib.bridge.Bridge"; //$NON-NLS-1$ + + /** Link to the layout bridge */ + private final LayoutBridge mBridge; + /** Status of the layoutlib.jar loading */ + private final LoadStatus mStatus; + /** classloader used to load the jar file */ + private final ClassLoader mClassLoader; + + /** + * Returns the loaded {@link LayoutBridge} object or null if the loading failed. + */ + public LayoutBridge getBridge() { + return mBridge; + } + + /** + * Returns the {@link LoadStatus} of the loading of the layoutlib jar file. + */ + public LoadStatus getStatus() { + return mStatus; + } + + /** + * Returns the classloader used to load the classes in the layoutlib jar file. + */ + public ClassLoader getClassLoader() { + return mClassLoader; + } + + /** + * Loads the layoutlib.jar file located at the given path and returns a {@link LayoutLibrary} + * object representing the result. + * <p/> + * If loading failed {@link #getStatus()} will reflect this, and {@link #getBridge()} will + * return null. + * + * @param layoutLibJarOsPath the path of the jar file + * @param log an optional log file. + * @return a {@link LayoutLibrary} object always. + */ + public static LayoutLibrary load(String layoutLibJarOsPath, ILogger log) { + + LoadStatus status = LoadStatus.LOADING; + LayoutBridge bridge = null; + ClassLoader classLoader = null; + + try { + // get the URL for the file. + File f = new File(layoutLibJarOsPath); + if (f.isFile() == false) { + if (log != null) { + log.error(null, "layoutlib.jar is missing!"); //$NON-NLS-1$ + } + } else { + URI uri = f.toURI(); + URL url = uri.toURL(); + + // create a class loader. Because this jar reference interfaces + // that are in the editors plugin, it's important to provide + // a parent class loader. + classLoader = new URLClassLoader( + new URL[] { url }, + LayoutLibrary.class.getClassLoader()); + + // load the class + Class<?> clazz = classLoader.loadClass(CLASS_BRIDGE); + if (clazz != null) { + // instantiate an object of the class. + Constructor<?> constructor = clazz.getConstructor(); + if (constructor != null) { + Object bridgeObject = constructor.newInstance(); + if (bridgeObject instanceof LayoutBridge) { + bridge = (LayoutBridge)bridgeObject; + } else if (bridgeObject instanceof ILayoutBridge) { + bridge = new LayoutBridgeWrapper((ILayoutBridge) bridgeObject, + classLoader); + } + } + } + + if (bridge == null) { + status = LoadStatus.FAILED; + if (log != null) { + log.error(null, "Failed to load " + CLASS_BRIDGE); //$NON-NLS-1$ + } + } else { + // mark the lib as loaded. + status = LoadStatus.LOADED; + } + } + } catch (Throwable t) { + status = LoadStatus.FAILED; + // log the error. + if (log != null) { + log.error(t, "Failed to load the LayoutLib"); + } + } + + return new LayoutLibrary(bridge, classLoader, status); + } + + private LayoutLibrary(LayoutBridge bridge, ClassLoader classLoader, LoadStatus status) { + mBridge = bridge; + mClassLoader = classLoader; + mStatus = status; + } +} diff --git a/layoutlib_utils/src/com/android/layoutlib/utils/ResourceValue.java b/layoutlib_utils/src/com/android/ide/common/layoutlib/ResourceValue.java index 98b4de6..382d961 100644 --- a/layoutlib_utils/src/com/android/layoutlib/utils/ResourceValue.java +++ b/layoutlib_utils/src/com/android/ide/common/layoutlib/ResourceValue.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.layoutlib.utils; +package com.android.ide.common.layoutlib; import com.android.layoutlib.api.IResourceValue; diff --git a/layoutlib_utils/src/com/android/layoutlib/utils/StyleResourceValue.java b/layoutlib_utils/src/com/android/ide/common/layoutlib/StyleResourceValue.java index a32ac1b..721b16c 100644 --- a/layoutlib_utils/src/com/android/layoutlib/utils/StyleResourceValue.java +++ b/layoutlib_utils/src/com/android/ide/common/layoutlib/StyleResourceValue.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.layoutlib.utils; +package com.android.ide.common.layoutlib; import com.android.layoutlib.api.IResourceValue; import com.android.layoutlib.api.IStyleResourceValue; diff --git a/layoutlib_utils/src/com/android/layoutlib/utils/ValueResourceParser.java b/layoutlib_utils/src/com/android/ide/common/layoutlib/ValueResourceParser.java index 4682d90..c784f1f 100644 --- a/layoutlib_utils/src/com/android/layoutlib/utils/ValueResourceParser.java +++ b/layoutlib_utils/src/com/android/ide/common/layoutlib/ValueResourceParser.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.layoutlib.utils; +package com.android.ide.common.layoutlib; import org.xml.sax.Attributes; import org.xml.sax.SAXException; diff --git a/layoutlib_utils/src/com/android/ide/common/log/ILogger.java b/layoutlib_utils/src/com/android/ide/common/log/ILogger.java new file mode 100644 index 0000000..1ad602e --- /dev/null +++ b/layoutlib_utils/src/com/android/ide/common/log/ILogger.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2010 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.ide.common.log; + +import java.util.Formatter; + +public interface ILogger { + + /** + * Prints a warning message on stdout. + * <p/> + * The message will be tagged with "Warning" on the output so the caller does not + * need to put such a prefix in the format string. + * <p/> + * Implementations should only display warnings in verbose mode. + * + * @param warningFormat is an optional error format. If non-null, it will be printed + * using a {@link Formatter} with the provided arguments. + * @param args provides the arguments for warningFormat. + */ + void warning(String warningFormat, Object... args); + + /** + * Prints an error message on stderr. + * <p/> + * The message will be tagged with "Error" on the output so the caller does not + * need to put such a prefix in the format string. + * <p/> + * Implementation should always display errors, independent of verbose mode. + * + * @param t is an optional {@link Throwable} or {@link Exception}. If non-null, it's + * message will be printed out. + * @param errorFormat is an optional error format. If non-null, it will be printed + * using a {@link Formatter} with the provided arguments. + * @param args provides the arguments for errorFormat. + */ + void error(Throwable t, String errorFormat, Object... args); + + /** + * Prints a message as-is on stdout. + * <p/> + * Implementation should always display errors, independent of verbose mode. + * No prefix is used, the message is printed as-is after formatting. + * + * @param msgFormat is an optional error format. If non-null, it will be printed + * using a {@link Formatter} with the provided arguments. + * @param args provides the arguments for msgFormat. + */ + void printf(String msgFormat, Object... args); +} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/LoadStatus.java b/layoutlib_utils/src/com/android/ide/common/sdk/LoadStatus.java index e334d97..babbd63 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/LoadStatus.java +++ b/layoutlib_utils/src/com/android/ide/common/sdk/LoadStatus.java @@ -1,11 +1,11 @@ /* - * Copyright (C) 2008 The Android Open Source Project + * Copyright (C) 2010 The Android Open Source Project * - * Licensed under the Eclipse Public License, Version 1.0 (the "License"); + * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.eclipse.org/org/documents/epl-v10.php + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.ide.eclipse.adt.internal.sdk; +package com.android.ide.common.sdk; /** * Enum for loading status of various SDK parts. |