Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b84e3517 authored by Xavier Ducrohet's avatar Xavier Ducrohet Committed by Android Git Automerger
Browse files

am 5b9936f6: Merge "LayoutLib: Use special view cookie for include-merge case." into honeycomb

* commit '5b9936f6':
  LayoutLib: Use special view cookie for include-merge case.
parents 0ccac6e3 5b9936f6
Loading
Loading
Loading
Loading
+95 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.view;

import com.android.layoutlib.bridge.android.BridgeInflater;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import android.util.AttributeSet;

import java.io.IOException;

/**
 * Delegate used to provide new implementation of a select few methods of {@link LayoutInflater}
 *
 * Through the layoutlib_create tool, the original  methods of LayoutInflater have been replaced
 * by calls to methods of the same name in this delegate class.
 *
 */
public class LayoutInflater_Delegate {

    /**
     * Recursive method used to descend down the xml hierarchy and instantiate
     * views, instantiate their children, and then call onFinishInflate().
     */
    /*package*/ static void rInflate(LayoutInflater thisInflater,
            XmlPullParser parser, View parent, final AttributeSet attrs,
            boolean finishInflate) throws XmlPullParserException, IOException {

        if (finishInflate == false) {
            // this is a merge rInflate!
            if (thisInflater instanceof BridgeInflater) {
                ((BridgeInflater) thisInflater).setIsInMerge(true);
            }
        }

        // ---- START DEFAULT IMPLEMENTATION.

        final int depth = parser.getDepth();
        int type;

        while (((type = parser.next()) != XmlPullParser.END_TAG ||
                parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {

            if (type != XmlPullParser.START_TAG) {
                continue;
            }

            final String name = parser.getName();

            if (LayoutInflater.TAG_REQUEST_FOCUS.equals(name)) {
                thisInflater.parseRequestFocus(parser, parent);
            } else if (LayoutInflater.TAG_INCLUDE.equals(name)) {
                if (parser.getDepth() == 0) {
                    throw new InflateException("<include /> cannot be the root element");
                }
                thisInflater.parseInclude(parser, parent, attrs);
            } else if (LayoutInflater.TAG_MERGE.equals(name)) {
                throw new InflateException("<merge /> must be the root element");
            } else {
                final View view = thisInflater.createViewFromTag(parent, name, attrs);
                final ViewGroup viewGroup = (ViewGroup) parent;
                final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs);
                thisInflater.rInflate(parser, view, attrs, true);
                viewGroup.addView(view, params);
            }
        }

        if (finishInflate) parent.onFinishInflate();

        // ---- END DEFAULT IMPLEMENTATION.

        if (finishInflate == false) {
            // this is a merge rInflate!
            if (thisInflater instanceof BridgeInflater) {
                ((BridgeInflater) thisInflater).setIsInMerge(false);
            }
        }
    }
}
+15 −4
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.layoutlib.bridge.android;

import com.android.ide.common.rendering.api.IProjectCallback;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.ide.common.rendering.api.MergeCookie;
import com.android.ide.common.rendering.api.RenderResources;
import com.android.ide.common.rendering.api.ResourceValue;
import com.android.layoutlib.bridge.Bridge;
@@ -41,6 +42,7 @@ import java.io.FileReader;
public final class BridgeInflater extends LayoutInflater {

    private final IProjectCallback mProjectCallback;
    private boolean mIsInMerge = false;

    /**
     * List of class prefixes which are tried first by default.
@@ -211,8 +213,6 @@ public final class BridgeInflater extends LayoutInflater {
        return null;
    }



    private void setupViewInContext(View view, AttributeSet attrs) {
        if (getContext() instanceof BridgeContext) {
            BridgeContext bc = (BridgeContext) getContext();
@@ -222,9 +222,11 @@ public final class BridgeInflater extends LayoutInflater {
                // get the view key
                Object viewKey = parser.getViewCookie();

                // if there's no view key and the depth is 1 (ie this is the first tag),
                // if there's no view key and the depth is 1 (ie this is the first tag), or 2
                // (this is first item in included merge layout)
                // look for a previous parser in the context, and check if this one has a viewkey.
                if (viewKey == null && parser.getDepth() == 1) {
                int testDepth = mIsInMerge ? 2 : 1;
                if (viewKey == null && parser.getDepth() == testDepth) {
                    BridgeXmlBlockParser previousParser = bc.getPreviousParser();
                    if (previousParser != null) {
                        viewKey = previousParser.getViewCookie();
@@ -232,12 +234,21 @@ public final class BridgeInflater extends LayoutInflater {
                }

                if (viewKey != null) {
                    if (testDepth == 2) {
                        // include-merge case
                        viewKey = new MergeCookie(viewKey);
                    }

                    bc.addViewKey(view, viewKey);
                }
            }
        }
    }

    public void setIsInMerge(boolean isInMerge) {
        mIsInMerge = isInMerge;
    }

    @Override
    public LayoutInflater cloneInContext(Context newContext) {
        return new BridgeInflater(this, newContext);
+6 −1
Original line number Diff line number Diff line
@@ -104,7 +104,12 @@ public class TestDelegates extends TestCase {
                        parameters);

                // check that the method is static
                assertTrue((delegateMethod.getModifiers() & Modifier.STATIC) == Modifier.STATIC);
                assertTrue(
                        String.format(
                                "Delegate method %1$s for class %2$s is not static",
                                delegateMethod.getName(),
                                originalClass.getName()),
                        (delegateMethod.getModifiers() & Modifier.STATIC) == Modifier.STATIC);
            } catch (NoSuchMethodException e) {
                // compute a full class name that's long but not too long.
                StringBuilder sb = new StringBuilder(originalMethod.getName() + "(");
+2 −1
Original line number Diff line number Diff line
@@ -96,8 +96,9 @@ public final class CreateInfo implements ICreateInfo {
    private final static String[] DELEGATE_METHODS = new String[] {
        "android.app.Fragment#instantiate", //(Landroid/content/Context;Ljava/lang/String;Landroid/os/Bundle;)Landroid/app/Fragment;",
        "android.os.Handler#sendMessageAtTime",
        "android.view.LayoutInflater#rInflate",
        "android.view.View#isInEditMode",
        "com.android.internal.util.XmlUtils#convertValueToInt"
        "com.android.internal.util.XmlUtils#convertValueToInt",
        // TODO: comment out once DelegateClass is working
        // "android.content.res.Resources$Theme#obtainStyledAttributes",
    };