aboutsummaryrefslogtreecommitdiffstats
path: root/ide_common
diff options
context:
space:
mode:
authorXavier Ducrohet <xav@android.com>2011-05-16 16:00:10 -0700
committerXavier Ducrohet <xav@android.com>2011-05-16 17:25:45 -0700
commit580ecb7a5212f5e14862aa91b8bc5a0964ca56d9 (patch)
treeadbd81323f7efe504c2f0703202209a314bf1dad /ide_common
parentb001f6889ef4c41a9d07678b4f15c3aee6321a22 (diff)
downloadsdk-580ecb7a5212f5e14862aa91b8bc5a0964ca56d9.zip
sdk-580ecb7a5212f5e14862aa91b8bc5a0964ca56d9.tar.gz
sdk-580ecb7a5212f5e14862aa91b8bc5a0964ca56d9.tar.bz2
Add baseline/margins to ViewInfo.
Also make it so that older layoutlib that are using API5 return the value through reflection (done in LayoutLibrary.) Change-Id: I3a32666e525f0f1d37a13e670d1d1c659b8e2027
Diffstat (limited to 'ide_common')
-rw-r--r--ide_common/src/com/android/ide/common/rendering/LayoutLibrary.java185
1 files changed, 160 insertions, 25 deletions
diff --git a/ide_common/src/com/android/ide/common/rendering/LayoutLibrary.java b/ide_common/src/com/android/ide/common/rendering/LayoutLibrary.java
index e1256fe..dd1a3dc 100644
--- a/ide_common/src/com/android/ide/common/rendering/LayoutLibrary.java
+++ b/ide_common/src/com/android/ide/common/rendering/LayoutLibrary.java
@@ -16,7 +16,7 @@
package com.android.ide.common.rendering;
-import static com.android.ide.common.rendering.api.Result.Status.NOT_IMPLEMENTED;
+import static com.android.ide.common.rendering.api.Result.Status.ERROR_REFLECTION;
import com.android.ide.common.log.ILogger;
import com.android.ide.common.rendering.api.Bridge;
@@ -48,11 +48,13 @@ import java.awt.image.BufferedImage;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
+import java.lang.reflect.Method;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@@ -91,6 +93,16 @@ public class LayoutLibrary {
/** classloader used to load the jar file */
private final ClassLoader mClassLoader;
+ // Reflection data for older Layout Libraries.
+ private Method mViewGetParentMethod;
+ private Method mViewGetBaselineMethod;
+ private Method mViewParentIndexOfChildMethod;
+ private Class<?> mMarginLayoutParamClass;
+ private Field mLeftMarginField;
+ private Field mTopMarginField;
+ private Field mRightMarginField;
+ private Field mBottomMarginField;
+
/**
* Returns the {@link LoadStatus} of the loading of the layoutlib jar file.
*/
@@ -282,7 +294,18 @@ public class LayoutLibrary {
*/
public RenderSession createSession(SessionParams params) {
if (mBridge != null) {
- return mBridge.createSession(params);
+ RenderSession session = mBridge.createSession(params);
+ if (params.getExtendedViewInfoMode() &&
+ mBridge.getCapabilities().contains(Capability.EXTENDED_VIEWINFO) == false) {
+ // Extended view info was requested but the layoutlib does not support it.
+ // Add it manually.
+ List<ViewInfo> infoList = session.getRootViews();
+ for (ViewInfo info : infoList) {
+ addExtendedViewInfo(info);
+ }
+ }
+
+ return session;
} else if (mLegacyBridge != null) {
return createLegacySession(params);
}
@@ -333,10 +356,13 @@ public class LayoutLibrary {
*/
public Result getViewParent(Object viewObject) {
if (mBridge != null) {
- return mBridge.getViewParent(viewObject);
+ Result r = mBridge.getViewParent(viewObject);
+ if (r.isSuccess()) {
+ return r;
+ }
}
- return NOT_IMPLEMENTED.createResult();
+ return getViewParentWithReflection(viewObject);
}
/**
@@ -348,30 +374,15 @@ public class LayoutLibrary {
*/
public Result getViewIndex(Object viewObject) {
if (mBridge != null) {
- return mBridge.getViewIndex(viewObject);
- }
-
- return NOT_IMPLEMENTED.createResult();
- }
-
- /**
- * Utility method returning the baseline value for a given view object. This basically returns
- * View.getBaseline().
- *
- * @param viewObject the object for which to return the index.
- *
- * @return the baseline value or -1 if not applicable to the view object or if this layout
- * library does not implement this method.
- */
- public int getViewBaseline(Object viewObject) {
- if (mBridge != null) {
- return mBridge.getViewBaseline(viewObject);
+ Result r = mBridge.getViewIndex(viewObject);
+ if (r.isSuccess()) {
+ return r;
+ }
}
- return -1;
+ return getViewIndexReflection(viewObject);
}
-
// ------ Implementation
private LayoutLibrary(Bridge bridge, ILayoutBridge legacyBridge, ClassLoader classLoader,
@@ -440,7 +451,6 @@ public class LayoutLibrary {
};
-
// convert the map of ResourceValue into IResourceValue. Super ugly but works.
Map<String, Map<String, IResourceValue>> projectMap = convertMap(
@@ -584,4 +594,129 @@ public class LayoutLibrary {
// do nothing.
}
}
+
+ private Result getViewParentWithReflection(Object viewObject) {
+ // default implementation using reflection.
+ try {
+ if (mViewGetParentMethod == null) {
+ Class<?> viewClass = Class.forName("android.view.View");
+ mViewGetParentMethod = viewClass.getMethod("getParent");
+ }
+
+ return Status.SUCCESS.createResult(mViewGetParentMethod.invoke(viewObject));
+ } catch (Exception e) {
+ // Catch all for the reflection calls.
+ return ERROR_REFLECTION.createResult(null, e);
+ }
+ }
+
+ /**
+ * Utility method returning the index of a given view in its parent.
+ * @param viewObject the object for which to return the index.
+ *
+ * @return a {@link Result} indicating the status of the action, and if success, the index in
+ * the parent in {@link Result#getData()}
+ */
+ private Result getViewIndexReflection(Object viewObject) {
+ // default implementation using reflection.
+ try {
+ Class<?> viewClass = Class.forName("android.view.View");
+
+ if (mViewGetParentMethod == null) {
+ mViewGetParentMethod = viewClass.getMethod("getParent");
+ }
+
+ Object parentObject = mViewGetParentMethod.invoke(viewObject);
+
+ if (mViewParentIndexOfChildMethod == null) {
+ Class<?> viewParentClass = Class.forName("android.view.ViewParent");
+ mViewParentIndexOfChildMethod = viewParentClass.getMethod("indexOfChild",
+ viewClass);
+ }
+
+ return Status.SUCCESS.createResult(
+ mViewParentIndexOfChildMethod.invoke(parentObject, viewObject));
+ } catch (Exception e) {
+ // Catch all for the reflection calls.
+ return ERROR_REFLECTION.createResult(null, e);
+ }
+ }
+
+ private void addExtendedViewInfo(ViewInfo info) {
+ computeExtendedViewInfo(info);
+
+ List<ViewInfo> children = info.getChildren();
+ for (ViewInfo child : children) {
+ addExtendedViewInfo(child);
+ }
+ }
+
+ private void computeExtendedViewInfo(ViewInfo info) {
+ Object viewObject = info.getViewObject();
+ Object params = info.getLayoutParamsObject();
+
+ int baseLine = getViewBaselineReflection(viewObject);
+ int leftMargin = 0;
+ int topMargin = 0;
+ int rightMargin = 0;
+ int bottomMargin = 0;
+
+ try {
+ if (mMarginLayoutParamClass == null) {
+ mMarginLayoutParamClass = Class.forName(
+ "android.view.ViewGroup$MarginLayoutParams");
+
+ mLeftMarginField = mMarginLayoutParamClass.getField("leftMargin");
+ mTopMarginField = mMarginLayoutParamClass.getField("topMargin");
+ mRightMarginField = mMarginLayoutParamClass.getField("rightMargin");
+ mBottomMarginField = mMarginLayoutParamClass.getField("bottomMargin");
+ }
+
+ if (mMarginLayoutParamClass.isAssignableFrom(params.getClass())) {
+
+ leftMargin = (Integer)mLeftMarginField.get(params);
+ topMargin = (Integer)mTopMarginField.get(params);
+ rightMargin = (Integer)mRightMarginField.get(params);
+ bottomMargin = (Integer)mBottomMarginField.get(params);
+ }
+
+ } catch (Exception e) {
+ // just use 'unknown' value.
+ leftMargin = Integer.MIN_VALUE;
+ topMargin = Integer.MIN_VALUE;
+ rightMargin = Integer.MIN_VALUE;
+ bottomMargin = Integer.MIN_VALUE;
+ }
+
+ info.setExtendedInfo(baseLine, leftMargin, topMargin, rightMargin, bottomMargin);
+ }
+
+ /**
+ * Utility method returning the baseline value for a given view object. This basically returns
+ * View.getBaseline().
+ *
+ * @param viewObject the object for which to return the index.
+ *
+ * @return the baseline value or -1 if not applicable to the view object or if this layout
+ * library does not implement this method.
+ */
+ private int getViewBaselineReflection(Object viewObject) {
+ // default implementation using reflection.
+ try {
+ if (mViewGetBaselineMethod == null) {
+ Class<?> viewClass = Class.forName("android.view.View");
+ mViewGetBaselineMethod = viewClass.getMethod("getBaseline");
+ }
+
+ Object result = mViewGetBaselineMethod.invoke(viewObject);
+ if (result instanceof Integer) {
+ return ((Integer)result).intValue();
+ }
+
+ } catch (Exception e) {
+ // Catch all for the reflection calls.
+ }
+
+ return Integer.MIN_VALUE;
+ }
}