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

Commit ad7d65da authored by Alan Viverette's avatar Alan Viverette Committed by Android (Google) Code Review
Browse files

Merge "Add stacked padding mode to LayerDrawable"

parents a812ab87 5b10a723
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -10369,6 +10369,7 @@ package android.graphics.drawable {
    method public int getId(int);
    method public int getNumberOfLayers();
    method public int getOpacity();
    method public int getPaddingMode();
    method public void invalidateDrawable(android.graphics.drawable.Drawable);
    method public void scheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable, long);
    method public void setAlpha(int);
@@ -10377,7 +10378,10 @@ package android.graphics.drawable {
    method public void setId(int, int);
    method public void setLayerInset(int, int, int, int, int);
    method public void setOpacity(int);
    method public void setPaddingMode(int);
    method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
    field public static final int PADDING_MODE_NEST = 0; // 0x0
    field public static final int PADDING_MODE_STACK = 1; // 0x1
  }
  public class LevelListDrawable extends android.graphics.drawable.DrawableContainer {
+9 −1
Original line number Diff line number Diff line
@@ -4241,6 +4241,14 @@
        <!-- Indicates if the drawable needs to be mirrored when its layout direction is
             RTL (right-to-left). -->
        <attr name="autoMirrored" />
        <!-- Indicates how layer padding should affect the bounds of subsequent layers.
            The default value is nest. -->
        <attr name="paddingMode">
            <!-- Nest each layer inside the padding of the previous layer. -->
            <enum name="nest" value="0" />
            <!-- Stack each layer directly atop the previous layer. -->
            <enum name="stack" value="1" />
        </attr>
    </declare-styleable>

    <!-- Describes an item (or child) of a LayerDrawable. -->
@@ -4256,7 +4264,7 @@
        <!-- Drawable used to render the layer. -->
        <attr name="drawable" />
        <!-- Identifier of the layer. This can be used to retrieve the layer
             from a drawbable container. -->
             from a drawable container. -->
        <attr name="id" />
    </declare-styleable>

+229 −93
Original line number Diff line number Diff line
@@ -47,6 +47,15 @@ import java.io.IOException;
 * @attr ref android.R.styleable#LayerDrawableItem_id
*/
public class LayerDrawable extends Drawable implements Drawable.Callback {
    /**
     * Padding mode used to nest each layer inside the padding of the previous
     * layer.
     */
    public static final int PADDING_MODE_NEST = 0;

    /** Padding mode used to stack each layer directly atop the previous layer. */
    public static final int PADDING_MODE_STACK = 1;

    LayerState mLayerState;

    private int mOpacityOverride = PixelFormat.UNKNOWN;
@@ -55,8 +64,10 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
    private int[] mPaddingR;
    private int[] mPaddingB;

    private final Rect mCachedPadding = new Rect();
    private final Rect mTmpRect = new Rect();
    private boolean mMutated;
    private boolean mHasCachedPadding;

    /**
     * Create a new layer drawable with the list of specified layers.
@@ -122,6 +133,9 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
        setAutoMirrored(a.getBoolean(com.android.internal.R.styleable.LayerDrawable_autoMirrored,
                false));

        mLayerState.mPaddingMode = a.getInteger(
                com.android.internal.R.styleable.LayerDrawableItem_drawable, PADDING_MODE_NEST);

        a.recycle();

        final int innerDepth = parser.getDepth() + 1;
@@ -187,19 +201,20 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
     */
    private void addLayer(Drawable layer, int id, int left, int top, int right, int bottom) {
        final LayerState st = mLayerState;
        int N = st.mChildren != null ? st.mChildren.length : 0;
        int i = st.mNum;
        final int N = st.mChildren != null ? st.mChildren.length : 0;
        final int i = st.mNum;
        if (i >= N) {
            ChildDrawable[] nu = new ChildDrawable[N + 10];
            final ChildDrawable[] nu = new ChildDrawable[N + 10];
            if (i > 0) {
                System.arraycopy(st.mChildren, 0, nu, 0, i);
            }

            st.mChildren = nu;
        }

        mLayerState.mChildrenChangingConfigurations |= layer.getChangingConfigurations();

        ChildDrawable childDrawable = new ChildDrawable();
        final ChildDrawable childDrawable = new ChildDrawable();
        st.mChildren[i] = childDrawable;
        childDrawable.mId = id;
        childDrawable.mDrawable = layer;
@@ -221,8 +236,8 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
     */
    public Drawable findDrawableByLayerId(int id) {
        final ChildDrawable[] layers = mLayerState.mChildren;
        
        for (int i = mLayerState.mNum - 1; i >= 0; i--) {
        final int N = mLayerState.mNum;
        for (int i = 0; i < N; i--) {
            if (layers[i].mId == id) {
                return layers[i].mDrawable;
            }
@@ -281,20 +296,29 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
     */
    public boolean setDrawableByLayerId(int id, Drawable drawable) {
        final ChildDrawable[] layers = mLayerState.mChildren;
        
        for (int i = mLayerState.mNum - 1; i >= 0; i--) {
            if (layers[i].mId == id) {
                if (layers[i].mDrawable != null) {
        final int N = mLayerState.mNum;
        for (int i = 0; i < N; i++) {
            final ChildDrawable childDrawable = layers[i];
            if (childDrawable.mId == id) {
                if (childDrawable.mDrawable != null) {
                    if (drawable != null) {
                        Rect bounds = layers[i].mDrawable.getBounds();
                        final Rect bounds = childDrawable.mDrawable.getBounds();
                        drawable.setBounds(bounds);
                    }
                    layers[i].mDrawable.setCallback(null);

                    childDrawable.mDrawable.setCallback(null);
                }

                if (drawable != null) {
                    drawable.setCallback(this);
                }
                layers[i].mDrawable = drawable;

                childDrawable.mDrawable = drawable;

                if (refreshChildPadding(i, childDrawable)) {
                    invalidatePadding();
                }

                return true;
            }
        }
@@ -302,22 +326,58 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
        return false;
    }

    /** Specify modifiers to the bounds for the drawable[index].
        left += l
        top += t;
        right -= r;
        bottom -= b;
    /**
     * Specifies the insets in pixels for the drawable at the specified index.
     * Insets are used to adjust the drawable bounds.
     *
     * @param index the index of the drawable to adjust
     * @param l number of pixels to add to the left bound
     * @param t number of pixels to add to the top bound
     * @param r number of pixels to subtract from the right bound
     * @param b number of pixels to subtract from the bottom bound
     */
    public void setLayerInset(int index, int l, int t, int r, int b) {
        ChildDrawable childDrawable = mLayerState.mChildren[index];
        final ChildDrawable childDrawable = mLayerState.mChildren[index];
        childDrawable.mInsetL = l;
        childDrawable.mInsetT = t;
        childDrawable.mInsetR = r;
        childDrawable.mInsetB = b;
    }

    // overrides from Drawable.Callback
    /**
     * Specifies how layer padding should affect the bounds of subsequent
     * layers. The default value is {@link #PADDING_MODE_NEST}.
     *
     * @param mode padding mode, one of:
     *            <ul>
     *            <li>{@link #PADDING_MODE_NEST}
     *            <li>{@link #PADDING_MODE_STACK}
     *            </ul>
     */
    public void setPaddingMode(int mode) {
        if (mLayerState.mPaddingMode != mode) {
            mLayerState.mPaddingMode = mode;
            invalidatePadding();
        }
    }

    /**
     * @return the current padding mode
     * @see #setPaddingMode(int)
     */
    public int getPaddingMode() {
      return mLayerState.mPaddingMode;
    }

    /**
     * Invalidates cached padding.
     */
    private void invalidatePadding() {
        mHasCachedPadding = false;
        onBoundsChange(getBounds());
    }

    @Override
    public void invalidateDrawable(Drawable who) {
        final Callback callback = getCallback();
        if (callback != null) {
@@ -325,6 +385,7 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
        }
    }

    @Override
    public void scheduleDrawable(Drawable who, Runnable what, long when) {
        final Callback callback = getCallback();
        if (callback != null) {
@@ -332,6 +393,7 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
        }
    }

    @Override
    public void unscheduleDrawable(Drawable who, Runnable what) {
        final Callback callback = getCallback();
        if (callback != null) {
@@ -339,8 +401,6 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
        }
    }

    // overrides from Drawable

    @Override
    public void draw(Canvas canvas) {
        final ChildDrawable[] array = mLayerState.mChildren;
@@ -359,33 +419,69 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {

    @Override
    public boolean getPadding(Rect padding) {
        // Arbitrarily get the padding from the first image.
        // Technically we should maybe do something more intelligent,
        // like take the max padding of all the images.
        final Rect cachedPadding = mCachedPadding;
        if (!mHasCachedPadding) {
            if (mLayerState.mPaddingMode == PADDING_MODE_NEST) {
                computeNestedPadding(cachedPadding);
            } else {
                computeStackedPadding(cachedPadding);
            }

            mHasCachedPadding = true;
        }

        padding.set(cachedPadding);

        return padding.left != 0 || padding.top != 0 || padding.right != 0 || padding.bottom != 0;
    }

    private void computeNestedPadding(Rect padding) {
        padding.left = 0;
        padding.top = 0;
        padding.right = 0;
        padding.bottom = 0;

        // Add all the padding.
        final ChildDrawable[] array = mLayerState.mChildren;
        final int N = mLayerState.mNum;
        for (int i = 0; i < N; i++) {
            reapplyPadding(i, array[i]);
            refreshChildPadding(i, array[i]);

            padding.left += mPaddingL[i];
            padding.top += mPaddingT[i];
            padding.right += mPaddingR[i];
            padding.bottom += mPaddingB[i];
        }
        return true;
    }

    private void computeStackedPadding(Rect padding) {
        padding.left = 0;
        padding.top = 0;
        padding.right = 0;
        padding.bottom = 0;

        // Take the max padding.
        final ChildDrawable[] array = mLayerState.mChildren;
        final int N = mLayerState.mNum;
        for (int i = 0; i < N; i++) {
            refreshChildPadding(i, array[i]);

            padding.left = Math.max(padding.left, mPaddingL[i]);
            padding.top = Math.max(padding.top, mPaddingT[i]);
            padding.right = Math.max(padding.right, mPaddingR[i]);
            padding.bottom = Math.max(padding.bottom, mPaddingB[i]);
        }
    }

    @Override
    public boolean setVisible(boolean visible, boolean restart) {
        boolean changed = super.setVisible(visible, restart);
        final boolean changed = super.setVisible(visible, restart);
        final ChildDrawable[] array = mLayerState.mChildren;
        final int N = mLayerState.mNum;
        for (int i = 0; i < N; i++) {
            array[i].mDrawable.setVisible(visible, restart);
        }

        return changed;
    }

@@ -454,6 +550,7 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
    @Override
    public void setAutoMirrored(boolean mirrored) {
        mLayerState.mAutoMirrored = mirrored;

        final ChildDrawable[] array = mLayerState.mChildren;
        final int N = mLayerState.mNum;
        for (int i = 0; i < N; i++) {
@@ -473,102 +570,134 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {

    @Override
    protected boolean onStateChange(int[] state) {
        final ChildDrawable[] array = mLayerState.mChildren;
        final int N = mLayerState.mNum;
        boolean paddingChanged = false;
        boolean changed = false;

        final ChildDrawable[] array = mLayerState.mChildren;
        final int N = mLayerState.mNum;
        for (int i = 0; i < N; i++) {
            final ChildDrawable r = array[i];
            if (r.mDrawable.setState(state)) {
                changed = true;
            }
            if (reapplyPadding(i, r)) {

            if (refreshChildPadding(i, r)) {
                paddingChanged = true;
            }
        }

        if (paddingChanged) {
            onBoundsChange(getBounds());
            invalidatePadding();
        }

        return changed;
    }

    @Override
    protected boolean onLevelChange(int level) {
        final ChildDrawable[] array = mLayerState.mChildren;
        final int N = mLayerState.mNum;
        boolean paddingChanged = false;
        boolean changed = false;

        final ChildDrawable[] array = mLayerState.mChildren;
        final int N = mLayerState.mNum;
        for (int i = 0; i < N; i++) {
            final ChildDrawable r = array[i];
            if (r.mDrawable.setLevel(level)) {
                changed = true;
            }
            if (reapplyPadding(i, r)) {

            if (refreshChildPadding(i, r)) {
                paddingChanged = true;
            }
        }

        if (paddingChanged) {
            onBoundsChange(getBounds());
            invalidatePadding();
        }

        return changed;
    }

    @Override
    protected void onBoundsChange(Rect bounds) {
        int padL = 0;
        int padT = 0;
        int padR = 0;
        int padB = 0;

        final boolean nest = mLayerState.mPaddingMode == PADDING_MODE_NEST;
        final ChildDrawable[] array = mLayerState.mChildren;
        final int N = mLayerState.mNum;
        int padL=0, padT=0, padR=0, padB=0;
        for (int i = 0; i < N; i++) {
            final ChildDrawable r = array[i];
            r.mDrawable.setBounds(bounds.left + r.mInsetL + padL,
                                  bounds.top + r.mInsetT + padT,
                                  bounds.right - r.mInsetR - padR,
                                  bounds.bottom - r.mInsetB - padB);
            r.mDrawable.setBounds(bounds.left + r.mInsetL + padL, bounds.top + r.mInsetT + padT,
                    bounds.right - r.mInsetR - padR, bounds.bottom - r.mInsetB - padB);

            if (nest) {
                padL += mPaddingL[i];
                padR += mPaddingR[i];
                padT += mPaddingT[i];
                padB += mPaddingB[i];
            }
        }
    }

    @Override
    public int getIntrinsicWidth() {
        int width = -1;
        int padL = 0;
        int padR = 0;

        final boolean nest = mLayerState.mPaddingMode == PADDING_MODE_NEST;
        final ChildDrawable[] array = mLayerState.mChildren;
        final int N = mLayerState.mNum;
        int padL=0, padR=0;
        for (int i = 0; i < N; i++) {
            final ChildDrawable r = array[i];
            int w = r.mDrawable.getIntrinsicWidth()
                  + r.mInsetL + r.mInsetR + padL + padR;
            final int w = r.mDrawable.getIntrinsicWidth() + r.mInsetL + r.mInsetR + padL + padR;
            if (w > width) {
                width = w;
            }

            if (nest) {
                padL += mPaddingL[i];
                padR += mPaddingR[i];
            }
        }

        return width;
    }

    @Override
    public int getIntrinsicHeight() {
        int height = -1;
        int padT = 0;
        int padB = 0;

        final boolean nest = mLayerState.mPaddingMode == PADDING_MODE_NEST;
        final ChildDrawable[] array = mLayerState.mChildren;
        final int N = mLayerState.mNum;
        int padT=0, padB=0;
        for (int i = 0; i < N; i++) {
            final ChildDrawable r = array[i];
            int h = r.mDrawable.getIntrinsicHeight() + r.mInsetT + r.mInsetB + + padT + padB;
            int h = r.mDrawable.getIntrinsicHeight() + r.mInsetT + r.mInsetB + padT + padB;
            if (h > height) {
                height = h;
            }

            if (nest) {
                padT += mPaddingT[i];
                padB += mPaddingB[i];
            }
        }

        return height;
    }

    private boolean reapplyPadding(int i, ChildDrawable r) {
    /**
     * Refreshes the cached padding values for the specified child.
     *
     * @return true if the child's padding has changed
     */
    private boolean refreshChildPadding(int i, ChildDrawable r) {
        final Rect rect = mTmpRect;
        r.mDrawable.getPadding(rect);
        if (rect.left != mPaddingL[i] || rect.top != mPaddingT[i] ||
@@ -582,11 +711,15 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
        return false;
    }

    /**
     * Ensures the child padding caches are large enough.
     */
    private void ensurePadding() {
        final int N = mLayerState.mNum;
        if (mPaddingL != null && mPaddingL.length >= N) {
            return;
        }

        mPaddingL = new int[N];
        mPaddingT = new int[N];
        mPaddingR = new int[N];
@@ -651,6 +784,8 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {

        private boolean mAutoMirrored;

        private int mPaddingMode = PADDING_MODE_NEST;

        LayerState(LayerState orig, LayerDrawable owner, Resources res) {
            if (orig != null) {
                final ChildDrawable[] origChildDrawable = orig.mChildren;
@@ -685,6 +820,7 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
                mStateful = orig.mStateful;
                mCheckedConstantState = mCanConstantState = true;
                mAutoMirrored = orig.mAutoMirrored;
                mPaddingMode = orig.mPaddingMode;
            } else {
                mNum = 0;
                mChildren = null;