aboutsummaryrefslogtreecommitdiffstats
path: root/layoutlib_utils
diff options
context:
space:
mode:
authorXavier Ducrohet <xav@android.com>2010-11-10 16:18:58 -0800
committerXavier Ducrohet <xav@android.com>2010-11-11 12:15:58 -0800
commitf29be828de51dbe2f55508cd620142e35cd19cbd (patch)
tree0a0a6ec8b2ad6c4f09614f2a32ecf591d8f1d335 /layoutlib_utils
parent6c88ff3409763cac0d757bbcdf8f09d2bb5fda9e (diff)
downloadsdk-f29be828de51dbe2f55508cd620142e35cd19cbd.zip
sdk-f29be828de51dbe2f55508cd620142e35cd19cbd.tar.gz
sdk-f29be828de51dbe2f55508cd620142e35cd19cbd.tar.bz2
Make ADT use the new layoutlib API.
ADT now exclusively use the new API. The older platforms that still use the old API are accessed through a compatibility layer provided by the class LayoutBridgeWrapper that converts the old to the new API (both input and output). The wrapper and the loading code for the bridge have moved to layoutlib_utils, but into the ide.common package. Layoutlib_utils is to be renamed ide-common later. .sdk.LoadStatus has moved into .ide.common too since it's used by the bridge loading code. As we'll move more code into ide-common it's ok to have it there anyway. Also did some minor fix to the API: - missing implementation of ViewInfo - Made a singleton for SUCCESS state of SceneResult. Change-Id: I5e7130ca03b92ad71dc9c293b2ffc40566df645c
Diffstat (limited to 'layoutlib_utils')
-rw-r--r--layoutlib_utils/src/com/android/ide/common/layoutlib/BasicLayoutScene.java58
-rw-r--r--layoutlib_utils/src/com/android/ide/common/layoutlib/DensityBasedResourceValue.java (renamed from layoutlib_utils/src/com/android/layoutlib/utils/DensityBasedResourceValue.java)2
-rw-r--r--layoutlib_utils/src/com/android/ide/common/layoutlib/LayoutBridgeWrapper.java201
-rw-r--r--layoutlib_utils/src/com/android/ide/common/layoutlib/LayoutLibrary.java143
-rw-r--r--layoutlib_utils/src/com/android/ide/common/layoutlib/ResourceValue.java (renamed from layoutlib_utils/src/com/android/layoutlib/utils/ResourceValue.java)2
-rw-r--r--layoutlib_utils/src/com/android/ide/common/layoutlib/StyleResourceValue.java (renamed from layoutlib_utils/src/com/android/layoutlib/utils/StyleResourceValue.java)2
-rw-r--r--layoutlib_utils/src/com/android/ide/common/layoutlib/ValueResourceParser.java (renamed from layoutlib_utils/src/com/android/layoutlib/utils/ValueResourceParser.java)2
-rw-r--r--layoutlib_utils/src/com/android/ide/common/log/ILogger.java64
-rw-r--r--layoutlib_utils/src/com/android/ide/common/sdk/LoadStatus.java24
9 files changed, 494 insertions, 4 deletions
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/layoutlib_utils/src/com/android/ide/common/sdk/LoadStatus.java b/layoutlib_utils/src/com/android/ide/common/sdk/LoadStatus.java
new file mode 100644
index 0000000..babbd63
--- /dev/null
+++ b/layoutlib_utils/src/com/android/ide/common/sdk/LoadStatus.java
@@ -0,0 +1,24 @@
+/*
+ * 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.sdk;
+
+/**
+ * Enum for loading status of various SDK parts.
+ */
+public enum LoadStatus {
+ LOADING, LOADED, FAILED;
+}